]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-record-btrace.c
Fix value in comment of disassembled ARM type A opcodes.
[thirdparty/binutils-gdb.git] / gdb / python / py-record-btrace.c
CommitLineData
75c0bdf4
TW
1/* Python interface to btrace instruction history.
2
3 Copyright 2016-2017 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "gdbcmd.h"
23#include "gdbthread.h"
24#include "btrace.h"
25#include "py-record-btrace.h"
26#include "disasm.h"
27
28#if defined (IS_PY3K)
29
30#define BTPY_PYSLICE(x) (x)
31
32#else
33
34#define BTPY_PYSLICE(x) ((PySliceObject *) x)
35
36#endif
37
38#define BTPY_REQUIRE_VALID_INSN(obj, iter) \
39 do { \
40 struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
41 if (tinfo == NULL || btrace_is_empty (tinfo)) \
42 return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));\
43 if (0 == btrace_find_insn_by_number (&iter, &tinfo->btrace, \
44 obj->number)) \
45 return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));\
46 } while (0)
47
48#define BTPY_REQUIRE_VALID_CALL(obj, iter) \
49 do { \
50 struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
51 if (tinfo == NULL || btrace_is_empty (tinfo)) \
52 return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));\
53 if (0 == btrace_find_call_by_number (&iter, &tinfo->btrace, \
54 obj->number)) \
55 return PyErr_Format (gdbpy_gdb_error, _("No such call segment."));\
56 } while (0)
57
58/* This can either be a btrace instruction or a function call segment,
59 depending on the chosen type. */
60
61typedef struct {
62 PyObject_HEAD
63
64 /* The thread this object belongs to. */
65 ptid_t ptid;
66
67 /* Instruction number or function call segment number, depending on the type
68 of this object. */
69 Py_ssize_t number;
70} btpy_object;
71
72/* Python object for btrace record lists. */
73
74typedef struct {
75 PyObject_HEAD
76
77 /* The thread this list belongs to. */
78 ptid_t ptid;
79
80 /* The first index being part of this list. */
81 Py_ssize_t first;
82
83 /* The last index begin part of this list. */
84 Py_ssize_t last;
85
86 /* Stride size. */
87 Py_ssize_t step;
88
89 /* Either &BTPY_CALL_TYPE or &BTPY_INSN_TYPE. */
90 PyTypeObject* element_type;
91} btpy_list_object;
92
93/* Python type for btrace instructions. */
94
95static PyTypeObject btpy_insn_type = {
96 PyVarObject_HEAD_INIT (NULL, 0)
97};
98
99/* Python type for btrace function-calls. */
100
101static PyTypeObject btpy_call_type = {
102 PyVarObject_HEAD_INIT (NULL, 0)
103};
104
105/* Python type for btrace lists. */
106
107static PyTypeObject btpy_list_type = {
108 PyVarObject_HEAD_INIT (NULL, 0)
109};
110
111/* Create a new gdb.BtraceInstruction or gdb.BtraceFunctionCall object,
112 depending on TYPE. */
113
114static PyObject *
115btpy_new (ptid_t ptid, Py_ssize_t number, PyTypeObject* type)
116{
117 btpy_object * const obj = PyObject_New (btpy_object, type);
118
119 if (obj == NULL)
120 return NULL;
121
122 obj->ptid = ptid;
123 obj->number = number;
124
125 return (PyObject *) obj;
126}
127
128/* Create a new gdb.BtraceInstruction object. */
129
130static PyObject *
131btpy_insn_new (ptid_t ptid, Py_ssize_t number)
132{
133 return btpy_new (ptid, number, &btpy_insn_type);
134}
135
136/* Create a new gdb.BtraceFunctionCall object. */
137
138static PyObject *
139btpy_call_new (ptid_t ptid, Py_ssize_t number)
140{
141 return btpy_new (ptid, number, &btpy_call_type);
142}
143
144/* Create a new gdb.BtraceList object. */
145
146static PyObject *
147btpy_list_new (ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step,
148 PyTypeObject *element_type)
149{
150 btpy_list_object * const obj = PyObject_New (btpy_list_object,
151 &btpy_list_type);
152
153 if (obj == NULL)
154 return NULL;
155
156 obj->ptid = ptid;
157 obj->first = first;
158 obj->last = last;
159 obj->step = step;
160 obj->element_type = element_type;
161
162 return (PyObject *) obj;
163}
164
165/* Implementation of BtraceInstruction.number [int] and
166 BtraceFunctionCall.number [int]. */
167
168static PyObject *
169btpy_number (PyObject *self, void *closure)
170{
171 const btpy_object * const obj = (btpy_object *) self;
172
173 return PyInt_FromSsize_t (obj->number);
174}
175
176/* Implementation of BtraceInstruction.__hash__ () -> int and
177 BtraceFunctionCall.__hash__ () -> int. */
178
179static Py_hash_t
180btpy_hash (PyObject *self)
181{
182 const btpy_object * const obj = (btpy_object *) self;
183
184 return obj->number;
185}
186
187/* Implementation of BtraceInstruction.error [int]. Returns the
188 error code for gaps. */
189
190static PyObject *
191btpy_insn_error (PyObject *self, void *closure)
192{
193 const btpy_object * const obj = (btpy_object *) self;
194 struct btrace_insn_iterator iter;
195 int error;
196
197 BTPY_REQUIRE_VALID_INSN (obj, iter);
198
199 error = btrace_insn_get_error (&iter);
200
201 if (error == 0)
202 Py_RETURN_NONE;
203
204 return PyInt_FromLong (error);
205}
206
207/* Implementation of BtraceInstruction.sal [gdb.Symtab_and_line].
208 Return the SAL associated with this instruction. */
209
210static PyObject *
211btpy_insn_sal (PyObject *self, void *closure)
212{
213 const btpy_object * const obj = (btpy_object *) self;
214 const struct btrace_insn *insn;
215 struct btrace_insn_iterator iter;
216 PyObject *result = NULL;
217
218 BTPY_REQUIRE_VALID_INSN (obj, iter);
219
220 insn = btrace_insn_get (&iter);
221 if (insn == NULL)
222 Py_RETURN_NONE;
223
224 TRY
225 {
226 result = symtab_and_line_to_sal_object (find_pc_line (insn->pc, 0));
227 }
228 CATCH (except, RETURN_MASK_ALL)
229 {
230 GDB_PY_HANDLE_EXCEPTION (except);
231 }
232 END_CATCH
233
234 return result;
235}
236
237/* Implementation of BtraceInstruction.pc [int]. Returns
238 the instruction address. */
239
240static PyObject *
241btpy_insn_pc (PyObject *self, void *closure)
242{
243 const btpy_object * const obj = (btpy_object *) self;
244 const struct btrace_insn *insn;
245 struct btrace_insn_iterator iter;
246
247 BTPY_REQUIRE_VALID_INSN (obj, iter);
248
249 insn = btrace_insn_get (&iter);
250 if (insn == NULL)
251 Py_RETURN_NONE;
252
253 return gdb_py_long_from_ulongest (insn->pc);
254}
255
256/* Implementation of BtraceInstruction.size [int]. Returns
257 the instruction size. */
258
259static PyObject *
260btpy_insn_size (PyObject *self, void *closure)
261{
262 const btpy_object * const obj = (btpy_object *) self;
263 const struct btrace_insn *insn;
264 struct btrace_insn_iterator iter;
265
266 BTPY_REQUIRE_VALID_INSN (obj, iter);
267
268 insn = btrace_insn_get (&iter);
269 if (insn == NULL)
270 Py_RETURN_NONE;
271
272 return PyInt_FromLong (insn->size);
273}
274
275/* Implementation of BtraceInstruction.is_speculative [bool].
276 Returns if this instruction was executed speculatively. */
277
278static PyObject *
279btpy_insn_is_speculative (PyObject *self, void *closure)
280{
281 const btpy_object * const obj = (btpy_object *) self;
282 const struct btrace_insn *insn;
283 struct btrace_insn_iterator iter;
284
285 BTPY_REQUIRE_VALID_INSN (obj, iter);
286
287 insn = btrace_insn_get (&iter);
288 if (insn == NULL)
289 Py_RETURN_NONE;
290
291 if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
292 Py_RETURN_TRUE;
293 else
294 Py_RETURN_FALSE;
295}
296
297/* Implementation of BtraceInstruction.data [buffer].
298 Returns raw instruction data. */
299
300static PyObject *
301btpy_insn_data (PyObject *self, void *closure)
302{
303 const btpy_object * const obj = (btpy_object *) self;
304 const struct btrace_insn *insn;
305 struct btrace_insn_iterator iter;
306 gdb_byte *buffer = NULL;
307 PyObject *object;
308
309 BTPY_REQUIRE_VALID_INSN (obj, iter);
310
311 insn = btrace_insn_get (&iter);
312 if (insn == NULL)
313 Py_RETURN_NONE;
314
315 TRY
316 {
317 buffer = (gdb_byte *) xmalloc (insn->size);
318 read_memory (insn->pc, buffer, insn->size);
319 }
320 CATCH (except, RETURN_MASK_ALL)
321 {
322 xfree (buffer);
323 GDB_PY_HANDLE_EXCEPTION (except);
324 }
325 END_CATCH
326
327 object = PyBytes_FromStringAndSize ((const char*) buffer, insn->size);
328 xfree (buffer);
329
330 if (object == NULL)
331 return NULL;
332
cee59b3f 333#ifdef IS_PY3K
75c0bdf4 334 return PyMemoryView_FromObject (object);
cee59b3f
TW
335#else
336 return PyBuffer_FromObject (object, 0, Py_END_OF_BUFFER);
337#endif
338
75c0bdf4
TW
339}
340
341/* Implementation of BtraceInstruction.decode [str]. Returns
342 the instruction as human readable string. */
343
344static PyObject *
345btpy_insn_decode (PyObject *self, void *closure)
346{
347 const btpy_object * const obj = (btpy_object *) self;
348 const struct btrace_insn *insn;
349 struct btrace_insn_iterator iter;
350 string_file strfile;
351
352 BTPY_REQUIRE_VALID_INSN (obj, iter);
353
354 insn = btrace_insn_get (&iter);
355 if (insn == NULL)
356 {
357 int error_code = btrace_insn_get_error (&iter);
358 const struct btrace_config *config;
359
360 config = btrace_conf (&find_thread_ptid (obj->ptid)->btrace);
361 return PyBytes_FromString (btrace_decode_error (config->format,
362 error_code));
363 }
364
365 TRY
366 {
367 gdb_print_insn (target_gdbarch (), insn->pc, &strfile, NULL);
368 }
369 CATCH (except, RETURN_MASK_ALL)
370 {
371 gdbpy_convert_exception (except);
372 return NULL;
373 }
374 END_CATCH
375
376
377 return PyBytes_FromString (strfile.string ().c_str ());
378}
379
380/* Implementation of BtraceFunctionCall.level [int]. Returns the
381 call level. */
382
383static PyObject *
384btpy_call_level (PyObject *self, void *closure)
385{
386 const btpy_object * const obj = (btpy_object *) self;
387 const struct btrace_function *func;
388 struct btrace_call_iterator iter;
389
390 BTPY_REQUIRE_VALID_CALL (obj, iter);
391
392 func = btrace_call_get (&iter);
393 if (func == NULL)
394 Py_RETURN_NONE;
395
396 return PyInt_FromLong (iter.btinfo->level + func->level);
397}
398
399/* Implementation of BtraceFunctionCall.symbol [gdb.Symbol]. Returns
400 the symbol associated with this function call. */
401
402static PyObject *
403btpy_call_symbol (PyObject *self, void *closure)
404{
405 const btpy_object * const obj = (btpy_object *) self;
406 const struct btrace_function *func;
407 struct btrace_call_iterator iter;
408
409 BTPY_REQUIRE_VALID_CALL (obj, iter);
410
411 func = btrace_call_get (&iter);
412 if (func == NULL)
413 Py_RETURN_NONE;
414
415 if (func->sym == NULL)
416 Py_RETURN_NONE;
417
418 return symbol_to_symbol_object (func->sym);
419}
420
421/* Implementation of BtraceFunctionCall.instructions [list].
422 Return the list of instructions that belong to this function call. */
423
424static PyObject *
425btpy_call_instructions (PyObject *self, void *closure)
426{
427 const btpy_object * const obj = (btpy_object *) self;
428 const struct btrace_function *func;
429 struct btrace_call_iterator iter;
430 unsigned int len;
431
432 BTPY_REQUIRE_VALID_CALL (obj, iter);
433
434 func = btrace_call_get (&iter);
435 if (func == NULL)
436 Py_RETURN_NONE;
437
438 len = VEC_length (btrace_insn_s, func->insn);
439
440 /* Gaps count as one instruction. */
441 if (len == 0)
442 len = 1;
443
444 return btpy_list_new (obj->ptid, func->insn_offset, func->insn_offset + len,
445 1, &btpy_insn_type);
446}
447
448/* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall].
449 Return the caller / returnee of this function. */
450
451static PyObject *
452btpy_call_up (PyObject *self, void *closure)
453{
454 const btpy_object * const obj = (btpy_object *) self;
455 const struct btrace_function *func;
456 struct btrace_call_iterator iter;
457
458 BTPY_REQUIRE_VALID_CALL (obj, iter);
459
460 func = btrace_call_get (&iter);
461 if (func == NULL)
462 Py_RETURN_NONE;
463
464 if (func->up == NULL)
465 Py_RETURN_NONE;
466
467 return btpy_call_new (obj->ptid, func->up->number);
468}
469
470/* Implementation of BtraceFunctionCall.prev_sibling [BtraceFunctionCall].
471 Return a previous segment of this function. */
472
473static PyObject *
474btpy_call_prev_sibling (PyObject *self, void *closure)
475{
476 const btpy_object * const obj = (btpy_object *) self;
477 const struct btrace_function *func;
478 struct btrace_call_iterator iter;
479
480 BTPY_REQUIRE_VALID_CALL (obj, iter);
481
482 func = btrace_call_get (&iter);
483 if (func == NULL)
484 Py_RETURN_NONE;
485
486 if (func->segment.prev == NULL)
487 Py_RETURN_NONE;
488
489 return btpy_call_new (obj->ptid, func->segment.prev->number);
490}
491
492/* Implementation of BtraceFunctionCall.next_sibling [BtraceFunctionCall].
493 Return a following segment of this function. */
494
495static PyObject *
496btpy_call_next_sibling (PyObject *self, void *closure)
497{
498 const btpy_object * const obj = (btpy_object *) self;
499 const struct btrace_function *func;
500 struct btrace_call_iterator iter;
501
502 BTPY_REQUIRE_VALID_CALL (obj, iter);
503
504 func = btrace_call_get (&iter);
505 if (func == NULL)
506 Py_RETURN_NONE;
507
508 if (func->segment.next == NULL)
509 Py_RETURN_NONE;
510
511 return btpy_call_new (obj->ptid, func->segment.next->number);
512}
513
514/* Python rich compare function to allow for equality and inequality checks
515 in Python. */
516
517static PyObject *
518btpy_richcompare (PyObject *self, PyObject *other, int op)
519{
520 const btpy_object * const obj1 = (btpy_object *) self;
521 const btpy_object * const obj2 = (btpy_object *) other;
522
523 if (Py_TYPE (self) != Py_TYPE (other))
524 {
525 Py_INCREF (Py_NotImplemented);
526 return Py_NotImplemented;
527 }
528
529 switch (op)
530 {
531 case Py_EQ:
532 if (ptid_equal (obj1->ptid, obj2->ptid) && obj1->number == obj2->number)
533 Py_RETURN_TRUE;
534 else
535 Py_RETURN_FALSE;
536
537 case Py_NE:
538 if (!ptid_equal (obj1->ptid, obj2->ptid) || obj1->number != obj2->number)
539 Py_RETURN_TRUE;
540 else
541 Py_RETURN_FALSE;
542
543 default:
544 break;
545 }
546
547 Py_INCREF (Py_NotImplemented);
548 return Py_NotImplemented;
549}
550
551/* Implementation of BtraceList.__len__ (self) -> int. */
552
553static Py_ssize_t
554btpy_list_length (PyObject *self)
555{
556 const btpy_list_object * const obj = (btpy_list_object *) self;
557 const Py_ssize_t distance = obj->last - obj->first;
558 const Py_ssize_t result = distance / obj->step;
559
560 if ((distance % obj->step) == 0)
561 return result;
562
563 return result + 1;
564}
565
566/* Implementation of
567 BtraceList.__getitem__ (self, key) -> BtraceInstruction and
568 BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */
569
570static PyObject *
571btpy_list_item (PyObject *self, Py_ssize_t index)
572{
573 const btpy_list_object * const obj = (btpy_list_object *) self;
574 struct thread_info * const tinfo = find_thread_ptid (obj->ptid);
575
576 if (index < 0 || index >= btpy_list_length (self))
577 return PyErr_Format (PyExc_IndexError, _("Index out of range: %zd."),
578 index);
579
580 return btpy_new (obj->ptid, obj->first + (obj->step * index),
581 obj->element_type);
582}
583
584/* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
585
586static PyObject *
587btpy_list_slice (PyObject *self, PyObject *value)
588{
589 const btpy_list_object * const obj = (btpy_list_object *) self;
590 const Py_ssize_t length = btpy_list_length (self);
591 Py_ssize_t start, stop, step, slicelength;
592
593 if (PyInt_Check (value))
594 {
595 Py_ssize_t index = PyInt_AsSsize_t (value);
596
597 /* Emulate Python behavior for negative indices. */
598 if (index < 0)
599 index += length;
600
601 return btpy_list_item (self, index);
602 }
603
604 if (!PySlice_Check (value))
605 return PyErr_Format (PyExc_TypeError, _("Index must be int or slice."));
606
607 if (0 != PySlice_GetIndicesEx (BTPY_PYSLICE (value), length, &start, &stop,
608 &step, &slicelength))
609 return NULL;
610
611 return btpy_list_new (obj->ptid, obj->first + obj->step * start,
612 obj->first + obj->step * stop, obj->step * step,
613 obj->element_type);
614}
615
616/* Helper function that returns the position of an element in a BtraceList
617 or -1 if the element is not in the list. */
618
619static LONGEST
620btpy_list_position (PyObject *self, PyObject *value)
621{
622 const btpy_list_object * const list_obj = (btpy_list_object *) self;
623 const btpy_object * const obj = (btpy_object *) value;
624 Py_ssize_t index = obj->number;
625
626 if (list_obj->element_type != Py_TYPE (value))
627 return -1;
628
629 if (!ptid_equal (list_obj->ptid, obj->ptid))
630 return -1;
631
632 if (index < list_obj->first || index > list_obj->last)
633 return -1;
634
635 index -= list_obj->first;
636
637 if (index % list_obj->step != 0)
638 return -1;
639
640 return index / list_obj->step;
641}
642
643/* Implementation of "in" operator for BtraceLists. */
644
645static int
646btpy_list_contains (PyObject *self, PyObject *value)
647{
648 if (btpy_list_position (self, value) < 0)
649 return 0;
650
651 return 1;
652}
653
654/* Implementation of BtraceLists.index (self, value) -> int. */
655
656static PyObject *
657btpy_list_index (PyObject *self, PyObject *value)
658{
659 const LONGEST index = btpy_list_position (self, value);
660
661 if (index < 0)
662 return PyErr_Format (PyExc_ValueError, _("Not in list."));
663
664 return gdb_py_long_from_longest (index);
665}
666
667/* Implementation of BtraceList.count (self, value) -> int. */
668
669static PyObject *
670btpy_list_count (PyObject *self, PyObject *value)
671{
672 /* We know that if an element is in the list, it is so exactly one time,
673 enabling us to reuse the "is element of" check. */
674 return PyInt_FromLong (btpy_list_contains (self, value));
675}
676
677/* Python rich compare function to allow for equality and inequality checks
678 in Python. */
679
680static PyObject *
681btpy_list_richcompare (PyObject *self, PyObject *other, int op)
682{
683 const btpy_list_object * const obj1 = (btpy_list_object *) self;
684 const btpy_list_object * const obj2 = (btpy_list_object *) other;
685
686 if (Py_TYPE (self) != Py_TYPE (other))
687 {
688 Py_INCREF (Py_NotImplemented);
689 return Py_NotImplemented;
690 }
691
692 switch (op)
693 {
694 case Py_EQ:
695 if (ptid_equal (obj1->ptid, obj2->ptid)
696 && obj1->element_type == obj2->element_type
697 && obj1->first == obj2->first
698 && obj1->last == obj2->last
699 && obj1->step == obj2->step)
700 Py_RETURN_TRUE;
701 else
702 Py_RETURN_FALSE;
703
704 case Py_NE:
705 if (!ptid_equal (obj1->ptid, obj2->ptid)
706 || obj1->element_type != obj2->element_type
707 || obj1->first != obj2->first
708 || obj1->last != obj2->last
709 || obj1->step != obj2->step)
710 Py_RETURN_TRUE;
711 else
712 Py_RETURN_FALSE;
713
714 default:
715 break;
716 }
717
718 Py_INCREF (Py_NotImplemented);
719 return Py_NotImplemented;
720}
721
722/* Implementation of
723 BtraceRecord.method [str]. */
724
725PyObject *
726recpy_bt_method (PyObject *self, void *closure)
727{
728 return PyString_FromString ("btrace");
729}
730
731/* Implementation of
732 BtraceRecord.format [str]. */
733
734PyObject *
735recpy_bt_format (PyObject *self, void *closure)
736{
737 const struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
738 const struct btrace_config * config;
739
740 if (tinfo == NULL)
741 Py_RETURN_NONE;
742
743 config = btrace_conf (&tinfo->btrace);
744
745 if (config == NULL)
746 Py_RETURN_NONE;
747
748 return PyString_FromString (btrace_format_short_string (config->format));
749}
750
751/* Implementation of
752 BtraceRecord.replay_position [BtraceInstruction]. */
753
754PyObject *
755recpy_bt_replay_position (PyObject *self, void *closure)
756{
757 const struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
758
759 if (tinfo == NULL)
760 Py_RETURN_NONE;
761
762 if (tinfo->btrace.replay == NULL)
763 Py_RETURN_NONE;
764
765 return btpy_insn_new (inferior_ptid,
766 btrace_insn_number (tinfo->btrace.replay));
767}
768
769/* Implementation of
770 BtraceRecord.begin [BtraceInstruction]. */
771
772PyObject *
773recpy_bt_begin (PyObject *self, void *closure)
774{
775 struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
776 struct btrace_insn_iterator iterator;
777
778 if (tinfo == NULL)
779 Py_RETURN_NONE;
780
781 btrace_fetch (tinfo);
782
783 if (btrace_is_empty (tinfo))
784 Py_RETURN_NONE;
785
786 btrace_insn_begin (&iterator, &tinfo->btrace);
787 return btpy_insn_new (inferior_ptid, btrace_insn_number (&iterator));
788}
789
790/* Implementation of
791 BtraceRecord.end [BtraceInstruction]. */
792
793PyObject *
794recpy_bt_end (PyObject *self, void *closure)
795{
796 struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
797 struct btrace_insn_iterator iterator;
798
799 if (tinfo == NULL)
800 Py_RETURN_NONE;
801
802 btrace_fetch (tinfo);
803
804 if (btrace_is_empty (tinfo))
805 Py_RETURN_NONE;
806
807 btrace_insn_end (&iterator, &tinfo->btrace);
808 return btpy_insn_new (inferior_ptid, btrace_insn_number (&iterator));
809}
810
811/* Implementation of
812 BtraceRecord.instruction_history [list]. */
813
814PyObject *
815recpy_bt_instruction_history (PyObject *self, void *closure)
816{
817 struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
818 struct btrace_insn_iterator iterator;
819 unsigned long first = 0;
820 unsigned long last = 0;
821
822 if (tinfo == NULL)
823 Py_RETURN_NONE;
824
825 btrace_fetch (tinfo);
826
827 if (btrace_is_empty (tinfo))
828 Py_RETURN_NONE;
829
830 btrace_insn_begin (&iterator, &tinfo->btrace);
831 first = btrace_insn_number (&iterator);
832
833 btrace_insn_end (&iterator, &tinfo->btrace);
834 last = btrace_insn_number (&iterator);
835
836 return btpy_list_new (inferior_ptid, first, last, 1, &btpy_insn_type);
837}
838
839/* Implementation of
840 BtraceRecord.function_call_history [list]. */
841
842PyObject *
843recpy_bt_function_call_history (PyObject *self, void *closure)
844{
845 struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
846 struct btrace_call_iterator iterator;
847 unsigned long first = 0;
848 unsigned long last = 0;
849
850 if (tinfo == NULL)
851 Py_RETURN_NONE;
852
853 btrace_fetch (tinfo);
854
855 if (btrace_is_empty (tinfo))
856 Py_RETURN_NONE;
857
858 btrace_call_begin (&iterator, &tinfo->btrace);
859 first = btrace_call_number (&iterator);
860
861 btrace_call_end (&iterator, &tinfo->btrace);
862 last = btrace_call_number (&iterator);
863
864 return btpy_list_new (inferior_ptid, first, last, 1, &btpy_call_type);
865}
866
867/* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
868
869PyObject *
870recpy_bt_goto (PyObject *self, PyObject *args)
871{
872 struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
873 const btpy_object *obj;
874
875 if (tinfo == NULL || btrace_is_empty (tinfo))
876 return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));
877
878 if (!PyArg_ParseTuple (args, "O", &obj))
879 return NULL;
880
881 if (Py_TYPE (obj) != &btpy_insn_type)
882 return PyErr_Format (PyExc_TypeError, _("Argument must be instruction."));
883
884 TRY
885 {
886 struct btrace_insn_iterator iter;
887
888 btrace_insn_end (&iter, &tinfo->btrace);
889
890 if (btrace_insn_number (&iter) == obj->number)
891 target_goto_record_end ();
892 else
893 target_goto_record (obj->number);
894 }
895 CATCH (except, RETURN_MASK_ALL)
896 {
897 GDB_PY_HANDLE_EXCEPTION (except);
898 }
899 END_CATCH
900
901 Py_RETURN_NONE;
902}
903
904/* BtraceInstruction members. */
905
0d1f4ceb 906struct gdb_PyGetSetDef btpy_insn_getset[] =
75c0bdf4
TW
907{
908 { "number", btpy_number, NULL, "instruction number", NULL},
909 { "error", btpy_insn_error, NULL, "error number for gaps", NULL},
910 { "sal", btpy_insn_sal, NULL, "associated symbol and line", NULL},
911 { "pc", btpy_insn_pc, NULL, "instruction address", NULL},
912 { "data", btpy_insn_data, NULL, "raw instruction data", NULL},
913 { "decoded", btpy_insn_decode, NULL, "decoded instruction or error message \
914if the instruction is a gap", NULL},
915 { "size", btpy_insn_size, NULL, "instruction size in byte", NULL},
916 { "is_speculative", btpy_insn_is_speculative, NULL, "if the instruction was \
917executed speculatively", NULL},
918 {NULL}
919};
920
921/* BtraceFunctionCall members. */
922
0d1f4ceb 923static gdb_PyGetSetDef btpy_call_getset[] =
75c0bdf4
TW
924{
925 { "number", btpy_number, NULL, "function call number", NULL},
926 { "level", btpy_call_level, NULL, "call stack level", NULL},
927 { "symbol", btpy_call_symbol, NULL, "associated line and symbol", NULL},
928 { "instructions", btpy_call_instructions, NULL, "list of instructions in \
929this function segment", NULL},
930 { "up", btpy_call_up, NULL, "caller or returned-to function segment", NULL},
931 { "prev_sibling", btpy_call_prev_sibling, NULL, "previous segment of this \
932function", NULL},
933 { "next_sibling", btpy_call_next_sibling, NULL, "next segment of this \
934function", NULL},
935 {NULL}
936};
937
938/* BtraceList methods. */
939
940struct PyMethodDef btpy_list_methods[] =
941{
942 { "count", btpy_list_count, METH_O, "count number of occurences"},
943 { "index", btpy_list_index, METH_O, "index of entry"},
944 {NULL}
945};
946
947/* BtraceList sequence methods. */
948
949static PySequenceMethods btpy_list_sequence_methods =
950{
951 NULL
952};
953
954/* BtraceList mapping methods. Necessary for slicing. */
955
956static PyMappingMethods btpy_list_mapping_methods =
957{
958 NULL
959};
960
961/* Sets up the btrace record API. */
962
963int
964gdbpy_initialize_btrace (void)
965{
966 btpy_insn_type.tp_new = PyType_GenericNew;
967 btpy_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
968 btpy_insn_type.tp_basicsize = sizeof (btpy_object);
969 btpy_insn_type.tp_name = "gdb.BtraceInstruction";
970 btpy_insn_type.tp_doc = "GDB btrace instruction object";
971 btpy_insn_type.tp_getset = btpy_insn_getset;
972 btpy_insn_type.tp_richcompare = btpy_richcompare;
973 btpy_insn_type.tp_hash = btpy_hash;
974
975 btpy_call_type.tp_new = PyType_GenericNew;
976 btpy_call_type.tp_flags = Py_TPFLAGS_DEFAULT;
977 btpy_call_type.tp_basicsize = sizeof (btpy_object);
978 btpy_call_type.tp_name = "gdb.BtraceFunctionCall";
979 btpy_call_type.tp_doc = "GDB btrace call object";
980 btpy_call_type.tp_getset = btpy_call_getset;
981 btpy_call_type.tp_richcompare = btpy_richcompare;
982 btpy_call_type.tp_hash = btpy_hash;
983
984 btpy_list_type.tp_new = PyType_GenericNew;
985 btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
986 btpy_list_type.tp_basicsize = sizeof (btpy_list_object);
987 btpy_list_type.tp_name = "gdb.BtraceObjectList";
988 btpy_list_type.tp_doc = "GDB btrace list object";
989 btpy_list_type.tp_methods = btpy_list_methods;
990 btpy_list_type.tp_as_sequence = &btpy_list_sequence_methods;
991 btpy_list_type.tp_as_mapping = &btpy_list_mapping_methods;
992 btpy_list_type.tp_richcompare = btpy_list_richcompare;
993
994 btpy_list_sequence_methods.sq_item = btpy_list_item;
995 btpy_list_sequence_methods.sq_length = btpy_list_length;
996 btpy_list_sequence_methods.sq_contains = btpy_list_contains;
997
998 btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
999
1000 if (PyType_Ready (&btpy_insn_type) < 0
1001 || PyType_Ready (&btpy_call_type) < 0
1002 || PyType_Ready (&btpy_list_type) < 0)
1003 return -1;
1004 else
1005 return 0;
1006}