Python: Move and rename gdb.BtraceFunction

Remove gdb.BtraceFunctionCall and replace by gdb.FunctionSegment.  Additionally,
rename prev_segment and next_segment to prev and next.
This commit is contained in:
Tim Wiederhake 2017-05-02 11:35:54 +02:00
parent 0ed5da759e
commit 14f819c8c5
9 changed files with 309 additions and 221 deletions

View File

@ -1,3 +1,31 @@
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python/py-record-btrace.c (BTPY_REQUIRE_VALID_CALL, btpy_call_type):
Remove.
(btrace_func_from_recpy_func): New function.
(btpy_call_new, btpy_number, btpy_hash, btpy_richcompare): Remove.
(btpy_call_level, btpy_call_symbol, btpy_call_instructions,
btpy_call_up, btpy_call_prev_sibling, btpy_call_next_sibling): Rename to ...
(recpy_bt_func_level, recpy_bt_func_symbol, recpy_bt_func_instructions,
recpy_bt_func_up, recpy_bt_func_prev, recpy_bt_func_next): This.
Also, use new helper functions.
(btpy_list_item): Use new helper functions.
(recpy_bt_function_call_history): Use new type name.
(btpy_call_getset): Remove.
(gdbpy_initialize_btrace): Remove code to initialize
gdb.BtraceFunctionCall.
* python/py-record-btrace.h (recpy_bt_func_number, recpy_btb_func_level,
recpy_btb_func_symbol, recpy_bt_func_instructions, recpy_bt_func_up,
recpy_bt_func_prev, recpy_bt_func_next): New export.
* python/py-record.c (recpy_func_type): New static object.
(recpy_func_new, recpy_func_level, recpy_func_symbol,
recpy_func_instructions, recpy_func_up, recpy_func_prev,
recpy_func_next): New function.
(recpy_element_hash, recpy_element_richcompare): Updated comment.
(recpy_func_getset): New static object.
(gdbpy_initialize_record): Add code to initialize gdb.RecordInstruction.
* python/py-record.h (recpy_func_type, recpy_func_new): New export.
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python/py-record-btrace.c (BTPY_REQUIRE_VALID_INSN): Remove.

View File

@ -1,3 +1,9 @@
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python.texi (Recording in Python): Replace gdb.BtraceFunction with
gdb.RecordFunctionSegment. Rename prev_sibling and next_sibling to
prev and next.
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python.texi (Recording in Python): Replace gdb.BtraceInstruction with

View File

@ -3203,48 +3203,43 @@ the current recording method.
A human readable string with the reason for the gap.
@end defvar
The attributes and methods of function call objects depend on the
current recording format. Currently, only btrace function calls are
supported.
A @code{gdb.RecordFunctionSegment} object has the following attributes:
A @code{gdb.BtraceFunctionCall} object has the following attributes:
@defvar BtraceFunctionCall.number
An integer identifying this function call. @var{number} corresponds to
@defvar RecordFunctionSegment.number
An integer identifying this function segment. @code{number} corresponds to
the numbers seen in @code{record function-call-history}
(@pxref{Process Record and Replay}).
@end defvar
@defvar BtraceFunctionCall.symbol
@defvar RecordFunctionSegment.symbol
A @code{gdb.Symbol} object representing the associated symbol. May be
@code{None} if the function call is a gap or the debug symbols could
not be read.
@code{None} if no debug information is available.
@end defvar
@defvar BtraceFunctionCall.level
@defvar RecordFunctionSegment.level
An integer representing the function call's stack level. May be
@code{None} if the function call is a gap.
@end defvar
@defvar BtraceFunctionCall.instructions
@defvar RecordFunctionSegment.instructions
A list of @code{gdb.RecordInstruction} or @code{gdb.RecordGap} objects
associated with this function call.
@end defvar
@defvar BtraceFunctionCall.up
A @code{gdb.BtraceFunctionCall} object representing the caller's
@defvar RecordFunctionSegment.up
A @code{gdb.RecordFunctionSegment} object representing the caller's
function segment. If the call has not been recorded, this will be the
function segment to which control returns. If neither the call nor the
return have been recorded, this will be @code{None}.
@end defvar
@defvar BtraceFunctionCall.prev_sibling
A @code{gdb.BtraceFunctionCall} object representing the previous
@defvar RecordFunctionSegment.prev
A @code{gdb.RecordFunctionSegment} object representing the previous
segment of this function call. May be @code{None}.
@end defvar
@defvar BtraceFunctionCall.next_sibling
A @code{gdb.BtraceFunctionCall} object representing the next segment of
@defvar RecordFunctionSegment.next
A @code{gdb.RecordFunctionSegment} object representing the next segment of
this function call. May be @code{None}.
@end defvar

View File

@ -36,16 +36,6 @@
#endif
#define BTPY_REQUIRE_VALID_CALL(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_call_by_number (&iter, &tinfo->btrace, \
obj->number)) \
return PyErr_Format (gdbpy_gdb_error, _("No such call segment."));\
} while (0)
/* Python object for btrace record lists. */
typedef struct {
@ -67,12 +57,6 @@ typedef struct {
PyTypeObject* element_type;
} btpy_list_object;
/* Python type for btrace function-calls. */
static PyTypeObject btpy_call_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
/* Python type for btrace lists. */
static PyTypeObject btpy_list_type = {
@ -121,6 +105,49 @@ btrace_insn_from_recpy_insn (const PyObject * const pyobject)
return insn;
}
/* Returns either a btrace_function for the given Python
gdb.RecordFunctionSegment object or sets an appropriate Python exception and
returns NULL. */
static const btrace_function *
btrace_func_from_recpy_func (const PyObject * const pyobject)
{
const btrace_function *func;
const recpy_element_object *obj;
thread_info *tinfo;
btrace_call_iterator iter;
if (Py_TYPE (pyobject) != &recpy_func_type)
{
PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordFunctionSegment"));
return NULL;
}
obj = (const recpy_element_object *) pyobject;
tinfo = find_thread_ptid (obj->ptid);
if (tinfo == NULL || btrace_is_empty (tinfo))
{
PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
return NULL;
}
if (btrace_find_call_by_number (&iter, &tinfo->btrace, obj->number) == 0)
{
PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
return NULL;
}
func = btrace_call_get (&iter);
if (func == NULL)
{
PyErr_Format (gdbpy_gdb_error, _("Not a valid function segment."));
return NULL;
}
return func;
}
/* Looks at the recorded item with the number NUMBER and create a
gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */
@ -147,24 +174,6 @@ btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
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)
{
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 *
@ -186,28 +195,6 @@ btpy_list_new (ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step,
return (PyObject *) obj;
}
/* Implementation of BtraceInstruction.number [int] and
BtraceFunctionCall.number [int]. */
static PyObject *
btpy_number (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
return PyInt_FromSsize_t (obj->number);
}
/* Implementation of BtraceInstruction.__hash__ () -> int and
BtraceFunctionCall.__hash__ () -> int. */
static Py_hash_t
btpy_hash (PyObject *self)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
return obj->number;
}
/* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
Returns the SAL associated with this instruction. */
@ -344,40 +331,32 @@ recpy_bt_insn_decoded (PyObject *self, void *closure)
return PyBytes_FromString (strfile.string ().c_str ());
}
/* Implementation of BtraceFunctionCall.level [int]. Returns the
call level. */
/* Implementation of RecordFunctionSegment.level [int] for btrace.
Returns the call level. */
static PyObject *
btpy_call_level (PyObject *self, void *closure)
PyObject *
recpy_bt_func_level (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
thread_info *tinfo;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
return PyInt_FromLong (iter.btinfo->level + func->level);
tinfo = find_thread_ptid (((recpy_element_object *) self)->ptid);
return PyInt_FromLong (tinfo->btrace.level + func->level);
}
/* Implementation of BtraceFunctionCall.symbol [gdb.Symbol]. Returns
the symbol associated with this function call. */
/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol] for btrace.
Returns the symbol associated with this function call. */
static PyObject *
btpy_call_symbol (PyObject *self, void *closure)
PyObject *
recpy_bt_func_symbol (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
if (func->sym == NULL)
Py_RETURN_NONE;
@ -385,22 +364,17 @@ btpy_call_symbol (PyObject *self, void *closure)
return symbol_to_symbol_object (func->sym);
}
/* Implementation of BtraceFunctionCall.instructions [list].
Return the list of instructions that belong to this function call. */
/* Implementation of RecordFunctionSegment.instructions [list] for btrace.
Returns the list of instructions that belong to this function call. */
static PyObject *
btpy_call_instructions (PyObject *self, void *closure)
PyObject *
recpy_bt_func_instructions (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
unsigned int len;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
len = VEC_length (btrace_insn_s, func->insn);
@ -408,111 +382,63 @@ btpy_call_instructions (PyObject *self, void *closure)
if (len == 0)
len = 1;
return btpy_list_new (obj->ptid, func->insn_offset, func->insn_offset + len,
1, &recpy_insn_type);
return btpy_list_new (((recpy_element_object *) self)->ptid,
func->insn_offset, func->insn_offset + len, 1,
&recpy_insn_type);
}
/* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall].
Return the caller / returnee of this function. */
/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment] for
btrace. Returns the caller / returnee of this function. */
static PyObject *
btpy_call_up (PyObject *self, void *closure)
PyObject *
recpy_bt_func_up (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
if (func->up == NULL)
Py_RETURN_NONE;
return btpy_call_new (obj->ptid, func->up->number);
return recpy_func_new (((recpy_element_object *) self)->ptid,
RECORD_METHOD_BTRACE, func->up->number);
}
/* Implementation of BtraceFunctionCall.prev_sibling [BtraceFunctionCall].
Return a previous segment of this function. */
/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment] for
btrace. Returns a previous segment of this function. */
static PyObject *
btpy_call_prev_sibling (PyObject *self, void *closure)
PyObject *
recpy_bt_func_prev (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
if (func->segment.prev == NULL)
Py_RETURN_NONE;
return btpy_call_new (obj->ptid, func->segment.prev->number);
return recpy_func_new (((recpy_element_object *) self)->ptid,
RECORD_METHOD_BTRACE, func->segment.prev->number);
}
/* Implementation of BtraceFunctionCall.next_sibling [BtraceFunctionCall].
Return a following segment of this function. */
/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
btrace. Returns a following segment of this function. */
static PyObject *
btpy_call_next_sibling (PyObject *self, void *closure)
PyObject *
recpy_bt_func_next (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
const btrace_function * const func = btrace_func_from_recpy_func (self);
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL)
Py_RETURN_NONE;
return NULL;
if (func->segment.next == NULL)
Py_RETURN_NONE;
return btpy_call_new (obj->ptid, func->segment.next->number);
}
/* Python rich compare function to allow for equality and inequality checks
in Python. */
static PyObject *
btpy_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->number == obj2->number)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
case Py_NE:
if (!ptid_equal (obj1->ptid, obj2->ptid) || obj1->number != obj2->number)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
default:
break;
}
Py_INCREF (Py_NotImplemented);
return Py_NotImplemented;
return recpy_func_new (((recpy_element_object *) self)->ptid,
RECORD_METHOD_BTRACE, func->segment.next->number);
}
/* Implementation of BtraceList.__len__ (self) -> int. */
@ -550,7 +476,7 @@ btpy_list_item (PyObject *self, Py_ssize_t 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);
return recpy_func_new (obj->ptid, RECORD_METHOD_BTRACE, number);
}
/* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
@ -839,7 +765,7 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
btrace_call_end (&iterator, &tinfo->btrace);
last = btrace_call_number (&iterator);
return btpy_list_new (record->ptid, first, last, 1, &btpy_call_type);
return btpy_list_new (record->ptid, first, last, 1, &recpy_func_type);
}
/* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
@ -880,23 +806,6 @@ recpy_bt_goto (PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
/* BtraceFunctionCall members. */
static gdb_PyGetSetDef btpy_call_getset[] =
{
{ "number", btpy_number, NULL, "function call number", NULL},
{ "level", btpy_call_level, NULL, "call stack level", NULL},
{ "symbol", btpy_call_symbol, NULL, "associated line and symbol", NULL},
{ "instructions", btpy_call_instructions, NULL, "list of instructions in \
this function segment", NULL},
{ "up", btpy_call_up, NULL, "caller or returned-to function segment", NULL},
{ "prev_sibling", btpy_call_prev_sibling, NULL, "previous segment of this \
function", NULL},
{ "next_sibling", btpy_call_next_sibling, NULL, "next segment of this \
function", NULL},
{NULL}
};
/* BtraceList methods. */
struct PyMethodDef btpy_list_methods[] =
@ -925,15 +834,6 @@ static PyMappingMethods btpy_list_mapping_methods =
int
gdbpy_initialize_btrace (void)
{
btpy_call_type.tp_new = PyType_GenericNew;
btpy_call_type.tp_flags = Py_TPFLAGS_DEFAULT;
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_call_type.tp_richcompare = btpy_richcompare;
btpy_call_type.tp_hash = btpy_hash;
btpy_list_type.tp_new = PyType_GenericNew;
btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
btpy_list_type.tp_basicsize = sizeof (btpy_list_object);
@ -950,9 +850,5 @@ gdbpy_initialize_btrace (void)
btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
if (PyType_Ready (&btpy_call_type) < 0
|| PyType_Ready (&btpy_list_type) < 0)
return -1;
else
return 0;
return PyType_Ready (&btpy_list_type);
}

View File

@ -67,4 +67,25 @@ extern PyObject *recpy_bt_insn_size (PyObject *self, void *closure);
/* Implementation of RecordInstruction.is_speculative [bool]. */
extern PyObject *recpy_bt_insn_is_speculative (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.number [int]. */
extern PyObject *recpy_bt_func_number (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.number [int]. */
extern PyObject *recpy_bt_func_level (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol]. */
extern PyObject *recpy_bt_func_symbol (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.instructions [list]. */
extern PyObject *recpy_bt_func_instructions (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment]. */
extern PyObject *recpy_bt_func_up (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment]. */
extern PyObject *recpy_bt_func_prev (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */
extern PyObject *recpy_bt_func_next (PyObject *self, void *closure);
#endif /* GDB_PY_RECORD_BTRACE_H */

View File

@ -35,6 +35,12 @@ PyTypeObject recpy_insn_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
/* Python RecordFunctionSegment type. */
PyTypeObject recpy_func_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
/* Python RecordGap type. */
PyTypeObject recpy_gap_type = {
@ -262,7 +268,104 @@ recpy_insn_is_speculative (PyObject *self, void *closure)
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordInstruction.number [int]. */
/* Create a new gdb.RecordFunctionSegment object. */
PyObject *
recpy_func_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
{
recpy_element_object * const obj = PyObject_New (recpy_element_object,
&recpy_func_type);
if (obj == NULL)
return NULL;
obj->ptid = ptid;
obj->method = method;
obj->number = number;
return (PyObject *) obj;
}
/* Implementation of RecordFunctionSegment.level [int]. */
static PyObject *
recpy_func_level (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_level (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol]. */
static PyObject *
recpy_func_symbol (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_symbol (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordFunctionSegment.instructions [list]. */
static PyObject *
recpy_func_instructions (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_instructions (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment]. */
static PyObject *
recpy_func_up (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_up (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment]. */
static PyObject *
recpy_func_prev (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_prev (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */
static PyObject *
recpy_func_next (PyObject *self, void *closure)
{
const recpy_element_object * const obj = (recpy_element_object *) self;
if (obj->method == RECORD_METHOD_BTRACE)
return recpy_bt_func_next (self, closure);
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
/* Implementation of RecordInstruction.number [int] and
RecordFunctionSegment.number [int]. */
static PyObject *
recpy_element_number (PyObject *self, void* closure)
@ -272,7 +375,9 @@ recpy_element_number (PyObject *self, void* closure)
return PyInt_FromSsize_t (obj->number);
}
/* Implementation of RecordInstruction.__hash__ [int]. */
/* Implementation of RecordInstruction.__hash__ [int] and
RecordFunctionSegment.__hash__ [int]. */
static Py_hash_t
recpy_element_hash (PyObject *self)
{
@ -281,7 +386,8 @@ recpy_element_hash (PyObject *self)
return obj->number;
}
/* Implementation of operator == and != of RecordInstruction. */
/* Implementation of operator == and != of RecordInstruction and
RecordFunctionSegment. */
static PyObject *
recpy_element_richcompare (PyObject *self, PyObject *other, int op)
@ -411,6 +517,20 @@ static gdb_PyGetSetDef recpy_insn_getset[] = {
{ NULL }
};
/* RecordFunctionSegment member list. */
static gdb_PyGetSetDef recpy_func_getset[] = {
{ "number", recpy_element_number, NULL, "function segment number", NULL},
{ "level", recpy_func_level, NULL, "call stack level", NULL},
{ "symbol", recpy_func_symbol, NULL, "associated line and symbol", NULL},
{ "instructions", recpy_func_instructions, NULL, "list of instructions in \
this function segment", NULL},
{ "up", recpy_func_up, NULL, "caller or returned-to function segment", NULL},
{ "prev", recpy_func_prev, NULL, "previous segment of this function", NULL},
{ "next", recpy_func_next, NULL, "next segment of this function", NULL},
{ NULL }
};
/* RecordGap member list. */
static gdb_PyGetSetDef recpy_gap_getset[] = {
@ -442,6 +562,15 @@ gdbpy_initialize_record (void)
recpy_insn_type.tp_richcompare = recpy_element_richcompare;
recpy_insn_type.tp_hash = recpy_element_hash;
recpy_func_type.tp_new = PyType_GenericNew;
recpy_func_type.tp_flags = Py_TPFLAGS_DEFAULT;
recpy_func_type.tp_basicsize = sizeof (recpy_element_object);
recpy_func_type.tp_name = "gdb.RecordFunctionSegment";
recpy_func_type.tp_doc = "GDB record function segment object";
recpy_func_type.tp_getset = recpy_func_getset;
recpy_func_type.tp_richcompare = recpy_element_richcompare;
recpy_func_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);
@ -451,6 +580,7 @@ gdbpy_initialize_record (void)
if (PyType_Ready (&recpy_record_type) < 0
|| PyType_Ready (&recpy_insn_type) < 0
|| PyType_Ready (&recpy_func_type) < 0
|| PyType_Ready (&recpy_gap_type) < 0)
return -1;
else

View File

@ -56,10 +56,17 @@ typedef struct
/* Python RecordInstruction type. */
extern PyTypeObject recpy_insn_type;
/* Python RecordFunctionSegment type. */
extern PyTypeObject recpy_func_type;
/* Create a new gdb.RecordInstruction object. */
extern PyObject *recpy_insn_new (ptid_t ptid, enum record_method method,
Py_ssize_t number);
/* Create a new gdb.RecordFunctionSegment object. */
extern PyObject *recpy_func_new (ptid_t ptid, enum record_method method,
Py_ssize_t number);
/* Create a new gdb.RecordGap object. */
extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
Py_ssize_t number);

View File

@ -1,3 +1,8 @@
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.python/py-record-btrace.exp: Rename prev_sibling and next_sibling
to prev and next.
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.python/py-record-btrace.exp: Remove test for

View File

@ -99,8 +99,8 @@ with_test_prefix "function call" {
gdb_test "python print(c.level)" "$decimal"
gdb_test "python print(len(c.instructions))" "$decimal"
gdb_test "python print(c.up)" "None"
gdb_test "python print(c.prev_sibling)" "None"
gdb_test "python print(c == c.next_sibling.prev_sibling)" "True"
gdb_test "python print(c.prev)" "None"
gdb_test "python print(c == c.next.prev)" "True"
}
with_test_prefix "list" {