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>
|
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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
Loading…
Reference in New Issue