1 /* Python interface to btrace instruction history.
3 Copyright 2016-2017 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "gdbthread.h"
25 #include "py-record.h"
26 #include "py-record-btrace.h"
31 #define BTPY_PYSLICE(x) (x)
35 #define BTPY_PYSLICE(x) ((PySliceObject *) x)
39 #define BTPY_REQUIRE_VALID_INSN(obj, iter) \
41 struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
42 if (tinfo == NULL || btrace_is_empty (tinfo)) \
43 return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace.")); \
44 if (0 == btrace_find_insn_by_number (&iter, &tinfo->btrace, \
46 return PyErr_Format (gdbpy_gdb_error, _("No such instruction.")); \
49 #define BTPY_REQUIRE_VALID_CALL(obj, iter) \
51 struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
52 if (tinfo == NULL || btrace_is_empty (tinfo)) \
53 return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace.")); \
54 if (0 == btrace_find_call_by_number (&iter, &tinfo->btrace, \
56 return PyErr_Format (gdbpy_gdb_error, _("No such call segment."));\
59 /* This can either be a btrace instruction or a function call segment,
60 depending on the chosen type. */
65 /* The thread this object belongs to. */
68 /* Instruction number or function call segment number, depending on the type
73 /* Python object for btrace record lists. */
78 /* The thread this list belongs to. */
81 /* The first index being part of this list. */
84 /* The last index begin part of this list. */
90 /* Either &BTPY_CALL_TYPE or &BTPY_INSN_TYPE. */
91 PyTypeObject
* element_type
;
94 /* Python type for btrace instructions. */
96 static PyTypeObject btpy_insn_type
= {
97 PyVarObject_HEAD_INIT (NULL
, 0)
100 /* Python type for btrace function-calls. */
102 static PyTypeObject btpy_call_type
= {
103 PyVarObject_HEAD_INIT (NULL
, 0)
106 /* Python type for btrace lists. */
108 static PyTypeObject btpy_list_type
= {
109 PyVarObject_HEAD_INIT (NULL
, 0)
112 /* Create a new gdb.BtraceInstruction or gdb.BtraceFunctionCall object,
113 depending on TYPE. */
116 btpy_new (ptid_t ptid
, Py_ssize_t number
, PyTypeObject
* type
)
118 btpy_object
* const obj
= PyObject_New (btpy_object
, type
);
124 obj
->number
= number
;
126 return (PyObject
*) obj
;
129 /* Looks at the recorded item with the number NUMBER and create a
130 gdb.BtraceInstruction or gdb.RecordGap object for it accordingly. */
133 btpy_insn_or_gap_new (const thread_info
*tinfo
, Py_ssize_t number
)
135 btrace_insn_iterator iter
;
138 btrace_find_insn_by_number (&iter
, &tinfo
->btrace
, number
);
139 err_code
= btrace_insn_get_error (&iter
);
143 const btrace_config
*config
;
144 const char *err_string
;
146 config
= btrace_conf (&tinfo
->btrace
);
147 err_string
= btrace_decode_error (config
->format
, err_code
);
149 return recpy_gap_new (err_code
, err_string
, number
);
152 return btpy_new (tinfo
->ptid
, number
, &btpy_insn_type
);
155 /* Create a new gdb.BtraceFunctionCall object. */
158 btpy_call_new (ptid_t ptid
, Py_ssize_t number
)
160 return btpy_new (ptid
, number
, &btpy_call_type
);
163 /* Create a new gdb.BtraceList object. */
166 btpy_list_new (ptid_t ptid
, Py_ssize_t first
, Py_ssize_t last
, Py_ssize_t step
,
167 PyTypeObject
*element_type
)
169 btpy_list_object
* const obj
= PyObject_New (btpy_list_object
,
179 obj
->element_type
= element_type
;
181 return (PyObject
*) obj
;
184 /* Implementation of BtraceInstruction.number [int] and
185 BtraceFunctionCall.number [int]. */
188 btpy_number (PyObject
*self
, void *closure
)
190 const btpy_object
* const obj
= (btpy_object
*) self
;
192 return PyInt_FromSsize_t (obj
->number
);
195 /* Implementation of BtraceInstruction.__hash__ () -> int and
196 BtraceFunctionCall.__hash__ () -> int. */
199 btpy_hash (PyObject
*self
)
201 const btpy_object
* const obj
= (btpy_object
*) self
;
206 /* Implementation of BtraceInstruction.sal [gdb.Symtab_and_line].
207 Return the SAL associated with this instruction. */
210 btpy_insn_sal (PyObject
*self
, void *closure
)
212 const btpy_object
* const obj
= (btpy_object
*) self
;
213 const struct btrace_insn
*insn
;
214 struct btrace_insn_iterator iter
;
215 PyObject
*result
= NULL
;
217 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
219 insn
= btrace_insn_get (&iter
);
221 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
225 result
= symtab_and_line_to_sal_object (find_pc_line (insn
->pc
, 0));
227 CATCH (except
, RETURN_MASK_ALL
)
229 GDB_PY_HANDLE_EXCEPTION (except
);
236 /* Implementation of BtraceInstruction.pc [int]. Returns
237 the instruction address. */
240 btpy_insn_pc (PyObject
*self
, void *closure
)
242 const btpy_object
* const obj
= (btpy_object
*) self
;
243 const struct btrace_insn
*insn
;
244 struct btrace_insn_iterator iter
;
246 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
248 insn
= btrace_insn_get (&iter
);
250 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
252 return gdb_py_long_from_ulongest (insn
->pc
);
255 /* Implementation of BtraceInstruction.size [int]. Returns
256 the instruction size. */
259 btpy_insn_size (PyObject
*self
, void *closure
)
261 const btpy_object
* const obj
= (btpy_object
*) self
;
262 const struct btrace_insn
*insn
;
263 struct btrace_insn_iterator iter
;
265 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
267 insn
= btrace_insn_get (&iter
);
269 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
271 return PyInt_FromLong (insn
->size
);
274 /* Implementation of BtraceInstruction.is_speculative [bool].
275 Returns if this instruction was executed speculatively. */
278 btpy_insn_is_speculative (PyObject
*self
, void *closure
)
280 const btpy_object
* const obj
= (btpy_object
*) self
;
281 const struct btrace_insn
*insn
;
282 struct btrace_insn_iterator iter
;
284 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
286 insn
= btrace_insn_get (&iter
);
288 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
290 if (insn
->flags
& BTRACE_INSN_FLAG_SPECULATIVE
)
296 /* Implementation of BtraceInstruction.data [buffer].
297 Returns raw instruction data. */
300 btpy_insn_data (PyObject
*self
, void *closure
)
302 const btpy_object
* const obj
= (btpy_object
*) self
;
303 const struct btrace_insn
*insn
;
304 struct btrace_insn_iterator iter
;
305 gdb_byte
*buffer
= NULL
;
308 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
310 insn
= btrace_insn_get (&iter
);
312 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
316 buffer
= (gdb_byte
*) xmalloc (insn
->size
);
317 read_memory (insn
->pc
, buffer
, insn
->size
);
319 CATCH (except
, RETURN_MASK_ALL
)
322 GDB_PY_HANDLE_EXCEPTION (except
);
326 object
= PyBytes_FromStringAndSize ((const char*) buffer
, insn
->size
);
333 return PyMemoryView_FromObject (object
);
335 return PyBuffer_FromObject (object
, 0, Py_END_OF_BUFFER
);
340 /* Implementation of BtraceInstruction.decode [str]. Returns
341 the instruction as human readable string. */
344 btpy_insn_decode (PyObject
*self
, void *closure
)
346 const btpy_object
* const obj
= (btpy_object
*) self
;
347 const struct btrace_insn
*insn
;
348 struct btrace_insn_iterator iter
;
351 BTPY_REQUIRE_VALID_INSN (obj
, iter
);
353 insn
= btrace_insn_get (&iter
);
355 return PyErr_Format (gdbpy_gdb_error
, _("No such instruction."));
359 gdb_print_insn (target_gdbarch (), insn
->pc
, &strfile
, NULL
);
361 CATCH (except
, RETURN_MASK_ALL
)
363 gdbpy_convert_exception (except
);
369 return PyBytes_FromString (strfile
.string ().c_str ());
372 /* Implementation of BtraceFunctionCall.level [int]. Returns the
376 btpy_call_level (PyObject
*self
, void *closure
)
378 const btpy_object
* const obj
= (btpy_object
*) self
;
379 const struct btrace_function
*func
;
380 struct btrace_call_iterator iter
;
382 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
384 func
= btrace_call_get (&iter
);
388 return PyInt_FromLong (iter
.btinfo
->level
+ func
->level
);
391 /* Implementation of BtraceFunctionCall.symbol [gdb.Symbol]. Returns
392 the symbol associated with this function call. */
395 btpy_call_symbol (PyObject
*self
, void *closure
)
397 const btpy_object
* const obj
= (btpy_object
*) self
;
398 const struct btrace_function
*func
;
399 struct btrace_call_iterator iter
;
401 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
403 func
= btrace_call_get (&iter
);
407 if (func
->sym
== NULL
)
410 return symbol_to_symbol_object (func
->sym
);
413 /* Implementation of BtraceFunctionCall.instructions [list].
414 Return the list of instructions that belong to this function call. */
417 btpy_call_instructions (PyObject
*self
, void *closure
)
419 const btpy_object
* const obj
= (btpy_object
*) self
;
420 const struct btrace_function
*func
;
421 struct btrace_call_iterator iter
;
424 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
426 func
= btrace_call_get (&iter
);
430 len
= VEC_length (btrace_insn_s
, func
->insn
);
432 /* Gaps count as one instruction. */
436 return btpy_list_new (obj
->ptid
, func
->insn_offset
, func
->insn_offset
+ len
,
440 /* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall].
441 Return the caller / returnee of this function. */
444 btpy_call_up (PyObject
*self
, void *closure
)
446 const btpy_object
* const obj
= (btpy_object
*) self
;
447 const struct btrace_function
*func
;
448 struct btrace_call_iterator iter
;
450 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
452 func
= btrace_call_get (&iter
);
456 if (func
->up
== NULL
)
459 return btpy_call_new (obj
->ptid
, func
->up
->number
);
462 /* Implementation of BtraceFunctionCall.prev_sibling [BtraceFunctionCall].
463 Return a previous segment of this function. */
466 btpy_call_prev_sibling (PyObject
*self
, void *closure
)
468 const btpy_object
* const obj
= (btpy_object
*) self
;
469 const struct btrace_function
*func
;
470 struct btrace_call_iterator iter
;
472 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
474 func
= btrace_call_get (&iter
);
478 if (func
->segment
.prev
== NULL
)
481 return btpy_call_new (obj
->ptid
, func
->segment
.prev
->number
);
484 /* Implementation of BtraceFunctionCall.next_sibling [BtraceFunctionCall].
485 Return a following segment of this function. */
488 btpy_call_next_sibling (PyObject
*self
, void *closure
)
490 const btpy_object
* const obj
= (btpy_object
*) self
;
491 const struct btrace_function
*func
;
492 struct btrace_call_iterator iter
;
494 BTPY_REQUIRE_VALID_CALL (obj
, iter
);
496 func
= btrace_call_get (&iter
);
500 if (func
->segment
.next
== NULL
)
503 return btpy_call_new (obj
->ptid
, func
->segment
.next
->number
);
506 /* Python rich compare function to allow for equality and inequality checks
510 btpy_richcompare (PyObject
*self
, PyObject
*other
, int op
)
512 const btpy_object
* const obj1
= (btpy_object
*) self
;
513 const btpy_object
* const obj2
= (btpy_object
*) other
;
515 if (Py_TYPE (self
) != Py_TYPE (other
))
517 Py_INCREF (Py_NotImplemented
);
518 return Py_NotImplemented
;
524 if (ptid_equal (obj1
->ptid
, obj2
->ptid
) && obj1
->number
== obj2
->number
)
530 if (!ptid_equal (obj1
->ptid
, obj2
->ptid
) || obj1
->number
!= obj2
->number
)
539 Py_INCREF (Py_NotImplemented
);
540 return Py_NotImplemented
;
543 /* Implementation of BtraceList.__len__ (self) -> int. */
546 btpy_list_length (PyObject
*self
)
548 const btpy_list_object
* const obj
= (btpy_list_object
*) self
;
549 const Py_ssize_t distance
= obj
->last
- obj
->first
;
550 const Py_ssize_t result
= distance
/ obj
->step
;
552 if ((distance
% obj
->step
) == 0)
559 BtraceList.__getitem__ (self, key) -> BtraceInstruction and
560 BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */
563 btpy_list_item (PyObject
*self
, Py_ssize_t index
)
565 const btpy_list_object
* const obj
= (btpy_list_object
*) self
;
566 struct thread_info
* const tinfo
= find_thread_ptid (obj
->ptid
);
568 if (index
< 0 || index
>= btpy_list_length (self
))
569 return PyErr_Format (PyExc_IndexError
, _("Index out of range: %zd."),
572 return btpy_new (obj
->ptid
, obj
->first
+ (obj
->step
* index
),
576 /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
579 btpy_list_slice (PyObject
*self
, PyObject
*value
)
581 const btpy_list_object
* const obj
= (btpy_list_object
*) self
;
582 const Py_ssize_t length
= btpy_list_length (self
);
583 Py_ssize_t start
, stop
, step
, slicelength
;
585 if (PyInt_Check (value
))
587 Py_ssize_t index
= PyInt_AsSsize_t (value
);
589 /* Emulate Python behavior for negative indices. */
593 return btpy_list_item (self
, index
);
596 if (!PySlice_Check (value
))
597 return PyErr_Format (PyExc_TypeError
, _("Index must be int or slice."));
599 if (0 != PySlice_GetIndicesEx (BTPY_PYSLICE (value
), length
, &start
, &stop
,
600 &step
, &slicelength
))
603 return btpy_list_new (obj
->ptid
, obj
->first
+ obj
->step
* start
,
604 obj
->first
+ obj
->step
* stop
, obj
->step
* step
,
608 /* Helper function that returns the position of an element in a BtraceList
609 or -1 if the element is not in the list. */
612 btpy_list_position (PyObject
*self
, PyObject
*value
)
614 const btpy_list_object
* const list_obj
= (btpy_list_object
*) self
;
615 const btpy_object
* const obj
= (btpy_object
*) value
;
616 Py_ssize_t index
= obj
->number
;
618 if (list_obj
->element_type
!= Py_TYPE (value
))
621 if (!ptid_equal (list_obj
->ptid
, obj
->ptid
))
624 if (index
< list_obj
->first
|| index
> list_obj
->last
)
627 index
-= list_obj
->first
;
629 if (index
% list_obj
->step
!= 0)
632 return index
/ list_obj
->step
;
635 /* Implementation of "in" operator for BtraceLists. */
638 btpy_list_contains (PyObject
*self
, PyObject
*value
)
640 if (btpy_list_position (self
, value
) < 0)
646 /* Implementation of BtraceLists.index (self, value) -> int. */
649 btpy_list_index (PyObject
*self
, PyObject
*value
)
651 const LONGEST index
= btpy_list_position (self
, value
);
654 return PyErr_Format (PyExc_ValueError
, _("Not in list."));
656 return gdb_py_long_from_longest (index
);
659 /* Implementation of BtraceList.count (self, value) -> int. */
662 btpy_list_count (PyObject
*self
, PyObject
*value
)
664 /* We know that if an element is in the list, it is so exactly one time,
665 enabling us to reuse the "is element of" check. */
666 return PyInt_FromLong (btpy_list_contains (self
, value
));
669 /* Python rich compare function to allow for equality and inequality checks
673 btpy_list_richcompare (PyObject
*self
, PyObject
*other
, int op
)
675 const btpy_list_object
* const obj1
= (btpy_list_object
*) self
;
676 const btpy_list_object
* const obj2
= (btpy_list_object
*) other
;
678 if (Py_TYPE (self
) != Py_TYPE (other
))
680 Py_INCREF (Py_NotImplemented
);
681 return Py_NotImplemented
;
687 if (ptid_equal (obj1
->ptid
, obj2
->ptid
)
688 && obj1
->element_type
== obj2
->element_type
689 && obj1
->first
== obj2
->first
690 && obj1
->last
== obj2
->last
691 && obj1
->step
== obj2
->step
)
697 if (!ptid_equal (obj1
->ptid
, obj2
->ptid
)
698 || obj1
->element_type
!= obj2
->element_type
699 || obj1
->first
!= obj2
->first
700 || obj1
->last
!= obj2
->last
701 || obj1
->step
!= obj2
->step
)
710 Py_INCREF (Py_NotImplemented
);
711 return Py_NotImplemented
;
715 BtraceRecord.method [str]. */
718 recpy_bt_method (PyObject
*self
, void *closure
)
720 return PyString_FromString ("btrace");
724 BtraceRecord.format [str]. */
727 recpy_bt_format (PyObject
*self
, void *closure
)
729 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
730 const struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
731 const struct btrace_config
* config
;
736 config
= btrace_conf (&tinfo
->btrace
);
741 return PyString_FromString (btrace_format_short_string (config
->format
));
745 BtraceRecord.replay_position [BtraceInstruction]. */
748 recpy_bt_replay_position (PyObject
*self
, void *closure
)
750 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
751 const struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
756 if (tinfo
->btrace
.replay
== NULL
)
759 return btpy_insn_or_gap_new (tinfo
,
760 btrace_insn_number (tinfo
->btrace
.replay
));
764 BtraceRecord.begin [BtraceInstruction]. */
767 recpy_bt_begin (PyObject
*self
, void *closure
)
769 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
770 struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
771 struct btrace_insn_iterator iterator
;
776 btrace_fetch (tinfo
);
778 if (btrace_is_empty (tinfo
))
781 btrace_insn_begin (&iterator
, &tinfo
->btrace
);
782 return btpy_insn_or_gap_new (tinfo
, btrace_insn_number (&iterator
));
786 BtraceRecord.end [BtraceInstruction]. */
789 recpy_bt_end (PyObject
*self
, void *closure
)
791 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
792 struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
793 struct btrace_insn_iterator iterator
;
798 btrace_fetch (tinfo
);
800 if (btrace_is_empty (tinfo
))
803 btrace_insn_end (&iterator
, &tinfo
->btrace
);
804 return btpy_insn_or_gap_new (tinfo
, btrace_insn_number (&iterator
));
808 BtraceRecord.instruction_history [list]. */
811 recpy_bt_instruction_history (PyObject
*self
, void *closure
)
813 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
814 struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
815 struct btrace_insn_iterator iterator
;
816 unsigned long first
= 0;
817 unsigned long last
= 0;
822 btrace_fetch (tinfo
);
824 if (btrace_is_empty (tinfo
))
827 btrace_insn_begin (&iterator
, &tinfo
->btrace
);
828 first
= btrace_insn_number (&iterator
);
830 btrace_insn_end (&iterator
, &tinfo
->btrace
);
831 last
= btrace_insn_number (&iterator
);
833 return btpy_list_new (record
->ptid
, first
, last
, 1, &btpy_insn_type
);
837 BtraceRecord.function_call_history [list]. */
840 recpy_bt_function_call_history (PyObject
*self
, void *closure
)
842 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
843 struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
844 struct btrace_call_iterator iterator
;
845 unsigned long first
= 0;
846 unsigned long last
= 0;
851 btrace_fetch (tinfo
);
853 if (btrace_is_empty (tinfo
))
856 btrace_call_begin (&iterator
, &tinfo
->btrace
);
857 first
= btrace_call_number (&iterator
);
859 btrace_call_end (&iterator
, &tinfo
->btrace
);
860 last
= btrace_call_number (&iterator
);
862 return btpy_list_new (record
->ptid
, first
, last
, 1, &btpy_call_type
);
865 /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
868 recpy_bt_goto (PyObject
*self
, PyObject
*args
)
870 const recpy_record_object
* const record
= (recpy_record_object
*) self
;
871 struct thread_info
* const tinfo
= find_thread_ptid (record
->ptid
);
872 const btpy_object
*obj
;
874 if (tinfo
== NULL
|| btrace_is_empty (tinfo
))
875 return PyErr_Format (gdbpy_gdb_error
, _("Empty branch trace."));
877 if (!PyArg_ParseTuple (args
, "O", &obj
))
880 if (Py_TYPE (obj
) != &btpy_insn_type
)
881 return PyErr_Format (PyExc_TypeError
, _("Argument must be instruction."));
885 struct btrace_insn_iterator iter
;
887 btrace_insn_end (&iter
, &tinfo
->btrace
);
889 if (btrace_insn_number (&iter
) == obj
->number
)
890 target_goto_record_end ();
892 target_goto_record (obj
->number
);
894 CATCH (except
, RETURN_MASK_ALL
)
896 GDB_PY_HANDLE_EXCEPTION (except
);
903 /* BtraceInstruction members. */
905 struct gdb_PyGetSetDef btpy_insn_getset
[] =
907 { "number", btpy_number
, NULL
, "instruction number", NULL
},
908 { "sal", btpy_insn_sal
, NULL
, "associated symbol and line", NULL
},
909 { "pc", btpy_insn_pc
, NULL
, "instruction address", NULL
},
910 { "data", btpy_insn_data
, NULL
, "raw instruction data", NULL
},
911 { "decoded", btpy_insn_decode
, NULL
, "decoded instruction or error message \
912 if the instruction is a gap", NULL
},
913 { "size", btpy_insn_size
, NULL
, "instruction size in byte", NULL
},
914 { "is_speculative", btpy_insn_is_speculative
, NULL
, "if the instruction was \
915 executed speculatively", NULL
},
919 /* BtraceFunctionCall members. */
921 static gdb_PyGetSetDef btpy_call_getset
[] =
923 { "number", btpy_number
, NULL
, "function call number", NULL
},
924 { "level", btpy_call_level
, NULL
, "call stack level", NULL
},
925 { "symbol", btpy_call_symbol
, NULL
, "associated line and symbol", NULL
},
926 { "instructions", btpy_call_instructions
, NULL
, "list of instructions in \
927 this function segment", NULL
},
928 { "up", btpy_call_up
, NULL
, "caller or returned-to function segment", NULL
},
929 { "prev_sibling", btpy_call_prev_sibling
, NULL
, "previous segment of this \
931 { "next_sibling", btpy_call_next_sibling
, NULL
, "next segment of this \
936 /* BtraceList methods. */
938 struct PyMethodDef btpy_list_methods
[] =
940 { "count", btpy_list_count
, METH_O
, "count number of occurences"},
941 { "index", btpy_list_index
, METH_O
, "index of entry"},
945 /* BtraceList sequence methods. */
947 static PySequenceMethods btpy_list_sequence_methods
=
952 /* BtraceList mapping methods. Necessary for slicing. */
954 static PyMappingMethods btpy_list_mapping_methods
=
959 /* Sets up the btrace record API. */
962 gdbpy_initialize_btrace (void)
964 btpy_insn_type
.tp_new
= PyType_GenericNew
;
965 btpy_insn_type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
966 btpy_insn_type
.tp_basicsize
= sizeof (btpy_object
);
967 btpy_insn_type
.tp_name
= "gdb.BtraceInstruction";
968 btpy_insn_type
.tp_doc
= "GDB btrace instruction object";
969 btpy_insn_type
.tp_getset
= btpy_insn_getset
;
970 btpy_insn_type
.tp_richcompare
= btpy_richcompare
;
971 btpy_insn_type
.tp_hash
= btpy_hash
;
973 btpy_call_type
.tp_new
= PyType_GenericNew
;
974 btpy_call_type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
975 btpy_call_type
.tp_basicsize
= sizeof (btpy_object
);
976 btpy_call_type
.tp_name
= "gdb.BtraceFunctionCall";
977 btpy_call_type
.tp_doc
= "GDB btrace call object";
978 btpy_call_type
.tp_getset
= btpy_call_getset
;
979 btpy_call_type
.tp_richcompare
= btpy_richcompare
;
980 btpy_call_type
.tp_hash
= btpy_hash
;
982 btpy_list_type
.tp_new
= PyType_GenericNew
;
983 btpy_list_type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
984 btpy_list_type
.tp_basicsize
= sizeof (btpy_list_object
);
985 btpy_list_type
.tp_name
= "gdb.BtraceObjectList";
986 btpy_list_type
.tp_doc
= "GDB btrace list object";
987 btpy_list_type
.tp_methods
= btpy_list_methods
;
988 btpy_list_type
.tp_as_sequence
= &btpy_list_sequence_methods
;
989 btpy_list_type
.tp_as_mapping
= &btpy_list_mapping_methods
;
990 btpy_list_type
.tp_richcompare
= btpy_list_richcompare
;
992 btpy_list_sequence_methods
.sq_item
= btpy_list_item
;
993 btpy_list_sequence_methods
.sq_length
= btpy_list_length
;
994 btpy_list_sequence_methods
.sq_contains
= btpy_list_contains
;
996 btpy_list_mapping_methods
.mp_subscript
= btpy_list_slice
;
998 if (PyType_Ready (&btpy_insn_type
) < 0
999 || PyType_Ready (&btpy_call_type
) < 0
1000 || PyType_Ready (&btpy_list_type
) < 0)