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> 2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python/py-record-btrace.c (BTPY_REQUIRE_VALID_INSN): Remove. * 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> 2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python.texi (Recording in Python): Replace gdb.BtraceInstruction with * 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. 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 A @code{gdb.RecordFunctionSegment} object has the following attributes:
current recording format. Currently, only btrace function calls are
supported.
A @code{gdb.BtraceFunctionCall} object has the following attributes: @defvar RecordFunctionSegment.number
An integer identifying this function segment. @code{number} corresponds to
@defvar BtraceFunctionCall.number
An integer identifying this function call. @var{number} corresponds to
the numbers seen in @code{record function-call-history} the numbers seen in @code{record function-call-history}
(@pxref{Process Record and Replay}). (@pxref{Process Record and Replay}).
@end defvar @end defvar
@defvar BtraceFunctionCall.symbol @defvar RecordFunctionSegment.symbol
A @code{gdb.Symbol} object representing the associated symbol. May be 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 @code{None} if no debug information is available.
not be read.
@end defvar @end defvar
@defvar BtraceFunctionCall.level @defvar RecordFunctionSegment.level
An integer representing the function call's stack level. May be An integer representing the function call's stack level. May be
@code{None} if the function call is a gap. @code{None} if the function call is a gap.
@end defvar @end defvar
@defvar BtraceFunctionCall.instructions @defvar RecordFunctionSegment.instructions
A list of @code{gdb.RecordInstruction} or @code{gdb.RecordGap} objects A list of @code{gdb.RecordInstruction} or @code{gdb.RecordGap} objects
associated with this function call. associated with this function call.
@end defvar @end defvar
@defvar BtraceFunctionCall.up @defvar RecordFunctionSegment.up
A @code{gdb.BtraceFunctionCall} object representing the caller's A @code{gdb.RecordFunctionSegment} object representing the caller's
function segment. If the call has not been recorded, this will be the 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 function segment to which control returns. If neither the call nor the
return have been recorded, this will be @code{None}. return have been recorded, this will be @code{None}.
@end defvar @end defvar
@defvar BtraceFunctionCall.prev_sibling @defvar RecordFunctionSegment.prev
A @code{gdb.BtraceFunctionCall} object representing the previous A @code{gdb.RecordFunctionSegment} object representing the previous
segment of this function call. May be @code{None}. segment of this function call. May be @code{None}.
@end defvar @end defvar
@defvar BtraceFunctionCall.next_sibling @defvar RecordFunctionSegment.next
A @code{gdb.BtraceFunctionCall} object representing the next segment of A @code{gdb.RecordFunctionSegment} object representing the next segment of
this function call. May be @code{None}. this function call. May be @code{None}.
@end defvar @end defvar

View File

@ -36,16 +36,6 @@
#endif #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. */ /* Python object for btrace record lists. */
typedef struct { typedef struct {
@ -67,12 +57,6 @@ typedef struct {
PyTypeObject* element_type; PyTypeObject* element_type;
} btpy_list_object; } btpy_list_object;
/* Python type for btrace function-calls. */
static PyTypeObject btpy_call_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
/* Python type for btrace lists. */ /* Python type for btrace lists. */
static PyTypeObject btpy_list_type = { static PyTypeObject btpy_list_type = {
@ -121,6 +105,49 @@ btrace_insn_from_recpy_insn (const PyObject * const pyobject)
return insn; 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 /* Looks at the recorded item with the number NUMBER and create a
gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */ 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); 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. */ /* Create a new gdb.BtraceList object. */
static PyObject * 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; 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. /* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
Returns the SAL associated with this instruction. */ 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 ()); return PyBytes_FromString (strfile.string ().c_str ());
} }
/* Implementation of BtraceFunctionCall.level [int]. Returns the /* Implementation of RecordFunctionSegment.level [int] for btrace.
call level. */ Returns the call level. */
static PyObject * PyObject *
btpy_call_level (PyObject *self, void *closure) recpy_bt_func_level (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func; thread_info *tinfo;
struct btrace_call_iterator iter;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) 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 /* Implementation of RecordFunctionSegment.symbol [gdb.Symbol] for btrace.
the symbol associated with this function call. */ Returns the symbol associated with this function call. */
static PyObject * PyObject *
btpy_call_symbol (PyObject *self, void *closure) recpy_bt_func_symbol (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func;
struct btrace_call_iterator iter;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) if (func == NULL)
Py_RETURN_NONE; return NULL;
if (func->sym == NULL) if (func->sym == NULL)
Py_RETURN_NONE; Py_RETURN_NONE;
@ -385,22 +364,17 @@ btpy_call_symbol (PyObject *self, void *closure)
return symbol_to_symbol_object (func->sym); return symbol_to_symbol_object (func->sym);
} }
/* Implementation of BtraceFunctionCall.instructions [list]. /* Implementation of RecordFunctionSegment.instructions [list] for btrace.
Return the list of instructions that belong to this function call. */ Returns the list of instructions that belong to this function call. */
static PyObject * PyObject *
btpy_call_instructions (PyObject *self, void *closure) recpy_bt_func_instructions (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func;
struct btrace_call_iterator iter;
unsigned int len; unsigned int len;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) if (func == NULL)
Py_RETURN_NONE; return NULL;
len = VEC_length (btrace_insn_s, func->insn); len = VEC_length (btrace_insn_s, func->insn);
@ -408,111 +382,63 @@ btpy_call_instructions (PyObject *self, void *closure)
if (len == 0) if (len == 0)
len = 1; len = 1;
return btpy_list_new (obj->ptid, func->insn_offset, func->insn_offset + len, return btpy_list_new (((recpy_element_object *) self)->ptid,
1, &recpy_insn_type); func->insn_offset, func->insn_offset + len, 1,
&recpy_insn_type);
} }
/* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall]. /* Implementation of RecordFunctionSegment.up [RecordFunctionSegment] for
Return the caller / returnee of this function. */ btrace. Returns the caller / returnee of this function. */
static PyObject * PyObject *
btpy_call_up (PyObject *self, void *closure) recpy_bt_func_up (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func;
struct btrace_call_iterator iter;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) if (func == NULL)
Py_RETURN_NONE; return NULL;
if (func->up == NULL) if (func->up == NULL)
Py_RETURN_NONE; 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]. /* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment] for
Return a previous segment of this function. */ btrace. Returns a previous segment of this function. */
static PyObject * PyObject *
btpy_call_prev_sibling (PyObject *self, void *closure) recpy_bt_func_prev (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func;
struct btrace_call_iterator iter;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) if (func == NULL)
Py_RETURN_NONE; return NULL;
if (func->segment.prev == NULL) if (func->segment.prev == NULL)
Py_RETURN_NONE; 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]. /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
Return a following segment of this function. */ btrace. Returns a following segment of this function. */
static PyObject * PyObject *
btpy_call_next_sibling (PyObject *self, void *closure) recpy_bt_func_next (PyObject *self, void *closure)
{ {
const recpy_element_object * const obj = (const recpy_element_object *) self; const btrace_function * const func = btrace_func_from_recpy_func (self);
const struct btrace_function *func;
struct btrace_call_iterator iter;
BTPY_REQUIRE_VALID_CALL (obj, iter);
func = btrace_call_get (&iter);
if (func == NULL) if (func == NULL)
Py_RETURN_NONE; return NULL;
if (func->segment.next == NULL) if (func->segment.next == NULL)
Py_RETURN_NONE; Py_RETURN_NONE;
return btpy_call_new (obj->ptid, func->segment.next->number); return recpy_func_new (((recpy_element_object *) self)->ptid,
} RECORD_METHOD_BTRACE, 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;
} }
/* Implementation of BtraceList.__len__ (self) -> int. */ /* 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) if (obj->element_type == &recpy_insn_type)
return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number); return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number);
else 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. */ /* 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); btrace_call_end (&iterator, &tinfo->btrace);
last = btrace_call_number (&iterator); 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. */ /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
@ -880,23 +806,6 @@ recpy_bt_goto (PyObject *self, PyObject *args)
Py_RETURN_NONE; 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. */ /* BtraceList methods. */
struct PyMethodDef btpy_list_methods[] = struct PyMethodDef btpy_list_methods[] =
@ -925,15 +834,6 @@ static PyMappingMethods btpy_list_mapping_methods =
int int
gdbpy_initialize_btrace (void) 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_new = PyType_GenericNew;
btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT; btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
btpy_list_type.tp_basicsize = sizeof (btpy_list_object); 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; btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
if (PyType_Ready (&btpy_call_type) < 0 return PyType_Ready (&btpy_list_type);
|| PyType_Ready (&btpy_list_type) < 0)
return -1;
else
return 0;
} }

View File

@ -67,4 +67,25 @@ extern PyObject *recpy_bt_insn_size (PyObject *self, void *closure);
/* Implementation of RecordInstruction.is_speculative [bool]. */ /* Implementation of RecordInstruction.is_speculative [bool]. */
extern PyObject *recpy_bt_insn_is_speculative (PyObject *self, void *closure); 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 */ #endif /* GDB_PY_RECORD_BTRACE_H */

View File

@ -35,6 +35,12 @@ PyTypeObject recpy_insn_type = {
PyVarObject_HEAD_INIT (NULL, 0) PyVarObject_HEAD_INIT (NULL, 0)
}; };
/* Python RecordFunctionSegment type. */
PyTypeObject recpy_func_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
/* Python RecordGap type. */ /* Python RecordGap type. */
PyTypeObject recpy_gap_type = { PyTypeObject recpy_gap_type = {
@ -262,7 +268,104 @@ recpy_insn_is_speculative (PyObject *self, void *closure)
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); 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 * static PyObject *
recpy_element_number (PyObject *self, void* closure) recpy_element_number (PyObject *self, void* closure)
@ -272,7 +375,9 @@ recpy_element_number (PyObject *self, void* closure)
return PyInt_FromSsize_t (obj->number); return PyInt_FromSsize_t (obj->number);
} }
/* Implementation of RecordInstruction.__hash__ [int]. */ /* Implementation of RecordInstruction.__hash__ [int] and
RecordFunctionSegment.__hash__ [int]. */
static Py_hash_t static Py_hash_t
recpy_element_hash (PyObject *self) recpy_element_hash (PyObject *self)
{ {
@ -281,7 +386,8 @@ recpy_element_hash (PyObject *self)
return obj->number; return obj->number;
} }
/* Implementation of operator == and != of RecordInstruction. */ /* Implementation of operator == and != of RecordInstruction and
RecordFunctionSegment. */
static PyObject * static PyObject *
recpy_element_richcompare (PyObject *self, PyObject *other, int op) recpy_element_richcompare (PyObject *self, PyObject *other, int op)
@ -411,6 +517,20 @@ static gdb_PyGetSetDef recpy_insn_getset[] = {
{ NULL } { 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. */ /* RecordGap member list. */
static gdb_PyGetSetDef recpy_gap_getset[] = { 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_richcompare = recpy_element_richcompare;
recpy_insn_type.tp_hash = recpy_element_hash; 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_new = PyType_GenericNew;
recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT; recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT;
recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object); recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object);
@ -451,6 +580,7 @@ gdbpy_initialize_record (void)
if (PyType_Ready (&recpy_record_type) < 0 if (PyType_Ready (&recpy_record_type) < 0
|| PyType_Ready (&recpy_insn_type) < 0 || PyType_Ready (&recpy_insn_type) < 0
|| PyType_Ready (&recpy_func_type) < 0
|| PyType_Ready (&recpy_gap_type) < 0) || PyType_Ready (&recpy_gap_type) < 0)
return -1; return -1;
else else

View File

@ -56,10 +56,17 @@ typedef struct
/* Python RecordInstruction type. */ /* Python RecordInstruction type. */
extern PyTypeObject recpy_insn_type; extern PyTypeObject recpy_insn_type;
/* Python RecordFunctionSegment type. */
extern PyTypeObject recpy_func_type;
/* Create a new gdb.RecordInstruction object. */ /* Create a new gdb.RecordInstruction object. */
extern PyObject *recpy_insn_new (ptid_t ptid, enum record_method method, extern PyObject *recpy_insn_new (ptid_t ptid, enum record_method method,
Py_ssize_t number); 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. */ /* Create a new gdb.RecordGap object. */
extern PyObject *recpy_gap_new (int reason_code, const char *reason_string, extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
Py_ssize_t number); 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> 2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.python/py-record-btrace.exp: Remove test for * 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(c.level)" "$decimal"
gdb_test "python print(len(c.instructions))" "$decimal" gdb_test "python print(len(c.instructions))" "$decimal"
gdb_test "python print(c.up)" "None" gdb_test "python print(c.up)" "None"
gdb_test "python print(c.prev_sibling)" "None" gdb_test "python print(c.prev)" "None"
gdb_test "python print(c == c.next_sibling.prev_sibling)" "True" gdb_test "python print(c == c.next.prev)" "True"
} }
with_test_prefix "list" { with_test_prefix "list" {