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:
parent
0ed5da759e
commit
14f819c8c5
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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" {
|
||||
|
Loading…
x
Reference in New Issue
Block a user