GDB (xrefs)
py-record-btrace.c
Go to the documentation of this file.
1 /* Python interface to btrace instruction history.
2 
3  Copyright 2016-2018 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.h"
26 #include "py-record-btrace.h"
27 #include "disasm.h"
28 
29 #if defined (IS_PY3K)
30 
31 #define BTPY_PYSLICE(x) (x)
32 
33 #else
34 
35 #define BTPY_PYSLICE(x) ((PySliceObject *) x)
36 
37 #endif
38 
39 /* Python object for btrace record lists. */
40 
41 typedef struct {
42  PyObject_HEAD
43 
44  /* The thread this list belongs to. */
46 
47  /* The first index being part of this list. */
48  Py_ssize_t first;
49 
50  /* The last index begin part of this list. */
51  Py_ssize_t last;
52 
53  /* Stride size. */
54  Py_ssize_t step;
55 
56  /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE. */
57  PyTypeObject* element_type;
59 
60 /* Python type for btrace lists. */
61 
62 static PyTypeObject btpy_list_type = {
63  PyVarObject_HEAD_INIT (NULL, 0)
64 };
65 
66 /* Returns either a btrace_insn for the given Python gdb.RecordInstruction
67  object or sets an appropriate Python exception and returns NULL. */
68 
69 static const btrace_insn *
70 btrace_insn_from_recpy_insn (const PyObject * const pyobject)
71 {
72  const btrace_insn *insn;
73  const recpy_element_object *obj;
74  thread_info *tinfo;
76 
77  if (Py_TYPE (pyobject) != &recpy_insn_type)
78  {
79  PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordInstruction"));
80  return NULL;
81  }
82 
83  obj = (const recpy_element_object *) pyobject;
84  tinfo = find_thread_ptid (obj->ptid);
85 
86  if (tinfo == NULL || btrace_is_empty (tinfo))
87  {
88  PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
89  return NULL;
90  }
91 
92  if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0)
93  {
94  PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
95  return NULL;
96  }
97 
98  insn = btrace_insn_get (&iter);
99  if (insn == NULL)
100  {
101  PyErr_Format (gdbpy_gdb_error, _("Not a valid instruction."));
102  return NULL;
103  }
104 
105  return insn;
106 }
107 
108 /* Returns either a btrace_function for the given Python
109  gdb.RecordFunctionSegment object or sets an appropriate Python exception and
110  returns NULL. */
111 
112 static const btrace_function *
113 btrace_func_from_recpy_func (const PyObject * const pyobject)
114 {
115  const btrace_function *func;
116  const recpy_element_object *obj;
117  thread_info *tinfo;
119 
120  if (Py_TYPE (pyobject) != &recpy_func_type)
121  {
122  PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordFunctionSegment"));
123  return NULL;
124  }
125 
126  obj = (const recpy_element_object *) pyobject;
127  tinfo = find_thread_ptid (obj->ptid);
128 
129  if (tinfo == NULL || btrace_is_empty (tinfo))
130  {
131  PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
132  return NULL;
133  }
134 
135  if (btrace_find_call_by_number (&iter, &tinfo->btrace, obj->number) == 0)
136  {
137  PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
138  return NULL;
139  }
140 
141  func = btrace_call_get (&iter);
142  if (func == NULL)
143  {
144  PyErr_Format (gdbpy_gdb_error, _("Not a valid function segment."));
145  return NULL;
146  }
147 
148  return func;
149 }
150 
151 /* Looks at the recorded item with the number NUMBER and create a
152  gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */
153 
154 static PyObject *
155 btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
156 {
158  int err_code;
159 
160  btrace_find_insn_by_number (&iter, &tinfo->btrace, number);
161  err_code = btrace_insn_get_error (&iter);
162 
163  if (err_code != 0)
164  {
165  const btrace_config *config;
166  const char *err_string;
167 
168  config = btrace_conf (&tinfo->btrace);
169  err_string = btrace_decode_error (config->format, err_code);
170 
171  return recpy_gap_new (err_code, err_string, number);
172  }
173 
174  return recpy_insn_new (tinfo->ptid, RECORD_METHOD_BTRACE, number);
175 }
176 
177 /* Create a new gdb.BtraceList object. */
178 
179 static PyObject *
180 btpy_list_new (ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step,
181  PyTypeObject *element_type)
182 {
183  btpy_list_object * const obj = PyObject_New (btpy_list_object,
184  &btpy_list_type);
185 
186  if (obj == NULL)
187  return NULL;
188 
189  obj->ptid = ptid;
190  obj->first = first;
191  obj->last = last;
192  obj->step = step;
193  obj->element_type = element_type;
194 
195  return (PyObject *) obj;
196 }
197 
198 /* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
199  Returns the SAL associated with this instruction. */
200 
201 PyObject *
202 recpy_bt_insn_sal (PyObject *self, void *closure)
203 {
204  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
205  PyObject *result = NULL;
206 
207  if (insn == NULL)
208  return NULL;
209 
210  TRY
211  {
212  result = symtab_and_line_to_sal_object (find_pc_line (insn->pc, 0));
213  }
214  CATCH (except, RETURN_MASK_ALL)
215  {
216  GDB_PY_HANDLE_EXCEPTION (except);
217  }
218  END_CATCH
219 
220  return result;
221 }
222 
223 /* Implementation of RecordInstruction.pc [int] for btrace.
224  Returns the instruction address. */
225 
226 PyObject *
227 recpy_bt_insn_pc (PyObject *self, void *closure)
228 {
229  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
230 
231  if (insn == NULL)
232  return NULL;
233 
234  return gdb_py_long_from_ulongest (insn->pc);
235 }
236 
237 /* Implementation of RecordInstruction.size [int] for btrace.
238  Returns the instruction size. */
239 
240 PyObject *
241 recpy_bt_insn_size (PyObject *self, void *closure)
242 {
243  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
244 
245  if (insn == NULL)
246  return NULL;
247 
248  return PyInt_FromLong (insn->size);
249 }
250 
251 /* Implementation of RecordInstruction.is_speculative [bool] for btrace.
252  Returns if this instruction was executed speculatively. */
253 
254 PyObject *
255 recpy_bt_insn_is_speculative (PyObject *self, void *closure)
256 {
257  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
258 
259  if (insn == NULL)
260  return NULL;
261 
263  Py_RETURN_TRUE;
264  else
265  Py_RETURN_FALSE;
266 }
267 
268 /* Implementation of RecordInstruction.data [buffer] for btrace.
269  Returns raw instruction data. */
270 
271 PyObject *
272 recpy_bt_insn_data (PyObject *self, void *closure)
273 {
274  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
275  gdb_byte *buffer = NULL;
276  PyObject *object;
277 
278  if (insn == NULL)
279  return NULL;
280 
281  TRY
282  {
283  buffer = (gdb_byte *) xmalloc (insn->size);
284  read_memory (insn->pc, buffer, insn->size);
285  }
286  CATCH (except, RETURN_MASK_ALL)
287  {
288  xfree (buffer);
289  GDB_PY_HANDLE_EXCEPTION (except);
290  }
291  END_CATCH
292 
293  object = PyBytes_FromStringAndSize ((const char*) buffer, insn->size);
294  xfree (buffer);
295 
296  if (object == NULL)
297  return NULL;
298 
299 #ifdef IS_PY3K
300  return PyMemoryView_FromObject (object);
301 #else
302  return PyBuffer_FromObject (object, 0, Py_END_OF_BUFFER);
303 #endif
304 
305 }
306 
307 /* Implementation of RecordInstruction.decoded [str] for btrace.
308  Returns the instruction as human readable string. */
309 
310 PyObject *
311 recpy_bt_insn_decoded (PyObject *self, void *closure)
312 {
313  const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
314  string_file strfile;
315 
316  if (insn == NULL)
317  return NULL;
318 
319  TRY
320  {
321  gdb_print_insn (target_gdbarch (), insn->pc, &strfile, NULL);
322  }
323  CATCH (except, RETURN_MASK_ALL)
324  {
325  gdbpy_convert_exception (except);
326  return NULL;
327  }
328  END_CATCH
329 
330 
331  return PyBytes_FromString (strfile.string ().c_str ());
332 }
333 
334 /* Implementation of RecordFunctionSegment.level [int] for btrace.
335  Returns the call level. */
336 
337 PyObject *
338 recpy_bt_func_level (PyObject *self, void *closure)
339 {
340  const btrace_function * const func = btrace_func_from_recpy_func (self);
341  thread_info *tinfo;
342 
343  if (func == NULL)
344  return NULL;
345 
346  tinfo = find_thread_ptid (((recpy_element_object *) self)->ptid);
347  return PyInt_FromLong (tinfo->btrace.level + func->level);
348 }
349 
350 /* Implementation of RecordFunctionSegment.symbol [gdb.Symbol] for btrace.
351  Returns the symbol associated with this function call. */
352 
353 PyObject *
354 recpy_bt_func_symbol (PyObject *self, void *closure)
355 {
356  const btrace_function * const func = btrace_func_from_recpy_func (self);
357 
358  if (func == NULL)
359  return NULL;
360 
361  if (func->sym == NULL)
362  Py_RETURN_NONE;
363 
364  return symbol_to_symbol_object (func->sym);
365 }
366 
367 /* Implementation of RecordFunctionSegment.instructions [list] for btrace.
368  Returns the list of instructions that belong to this function call. */
369 
370 PyObject *
371 recpy_bt_func_instructions (PyObject *self, void *closure)
372 {
373  const btrace_function * const func = btrace_func_from_recpy_func (self);
374  unsigned int len;
375 
376  if (func == NULL)
377  return NULL;
378 
379  len = func->insn.size ();
380 
381  /* Gaps count as one instruction. */
382  if (len == 0)
383  len = 1;
384 
385  return btpy_list_new (((recpy_element_object *) self)->ptid,
386  func->insn_offset, func->insn_offset + len, 1,
387  &recpy_insn_type);
388 }
389 
390 /* Implementation of RecordFunctionSegment.up [RecordFunctionSegment] for
391  btrace. Returns the caller / returnee of this function. */
392 
393 PyObject *
394 recpy_bt_func_up (PyObject *self, void *closure)
395 {
396  const btrace_function * const func = btrace_func_from_recpy_func (self);
397 
398  if (func == NULL)
399  return NULL;
400 
401  if (func->up == 0)
402  Py_RETURN_NONE;
403 
404  return recpy_func_new (((recpy_element_object *) self)->ptid,
406 }
407 
408 /* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment] for
409  btrace. Returns a previous segment of this function. */
410 
411 PyObject *
412 recpy_bt_func_prev (PyObject *self, void *closure)
413 {
414  const btrace_function * const func = btrace_func_from_recpy_func (self);
415 
416  if (func == NULL)
417  return NULL;
418 
419  if (func->prev == 0)
420  Py_RETURN_NONE;
421 
422  return recpy_func_new (((recpy_element_object *) self)->ptid,
423  RECORD_METHOD_BTRACE, func->prev);
424 }
425 
426 /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
427  btrace. Returns a following segment of this function. */
428 
429 PyObject *
430 recpy_bt_func_next (PyObject *self, void *closure)
431 {
432  const btrace_function * const func = btrace_func_from_recpy_func (self);
433 
434  if (func == NULL)
435  return NULL;
436 
437  if (func->next == 0)
438  Py_RETURN_NONE;
439 
440  return recpy_func_new (((recpy_element_object *) self)->ptid,
441  RECORD_METHOD_BTRACE, func->next);
442 }
443 
444 /* Implementation of BtraceList.__len__ (self) -> int. */
445 
446 static Py_ssize_t
447 btpy_list_length (PyObject *self)
448 {
449  const btpy_list_object * const obj = (btpy_list_object *) self;
450  const Py_ssize_t distance = obj->last - obj->first;
451  const Py_ssize_t result = distance / obj->step;
452 
453  if ((distance % obj->step) == 0)
454  return result;
455 
456  return result + 1;
457 }
458 
459 /* Implementation of
460  BtraceList.__getitem__ (self, key) -> BtraceInstruction and
461  BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */
462 
463 static PyObject *
464 btpy_list_item (PyObject *self, Py_ssize_t index)
465 {
466  const btpy_list_object * const obj = (btpy_list_object *) self;
467  Py_ssize_t number;
468 
469  if (index < 0 || index >= btpy_list_length (self))
470  return PyErr_Format (PyExc_IndexError, _("Index out of range: %zd."),
471  index);
472 
473  number = obj->first + (obj->step * index);
474 
475  if (obj->element_type == &recpy_insn_type)
476  return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number);
477  else
478  return recpy_func_new (obj->ptid, RECORD_METHOD_BTRACE, number);
479 }
480 
481 /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
482 
483 static PyObject *
484 btpy_list_slice (PyObject *self, PyObject *value)
485 {
486  const btpy_list_object * const obj = (btpy_list_object *) self;
487  const Py_ssize_t length = btpy_list_length (self);
488  Py_ssize_t start, stop, step, slicelength;
489 
490  if (PyInt_Check (value))
491  {
492  Py_ssize_t index = PyInt_AsSsize_t (value);
493 
494  /* Emulate Python behavior for negative indices. */
495  if (index < 0)
496  index += length;
497 
498  return btpy_list_item (self, index);
499  }
500 
501  if (!PySlice_Check (value))
502  return PyErr_Format (PyExc_TypeError, _("Index must be int or slice."));
503 
504  if (0 != PySlice_GetIndicesEx (BTPY_PYSLICE (value), length, &start, &stop,
505  &step, &slicelength))
506  return NULL;
507 
508  return btpy_list_new (obj->ptid, obj->first + obj->step * start,
509  obj->first + obj->step * stop, obj->step * step,
510  obj->element_type);
511 }
512 
513 /* Helper function that returns the position of an element in a BtraceList
514  or -1 if the element is not in the list. */
515 
516 static LONGEST
517 btpy_list_position (PyObject *self, PyObject *value)
518 {
519  const btpy_list_object * const list_obj = (btpy_list_object *) self;
520  const recpy_element_object * const obj = (const recpy_element_object *) value;
521  Py_ssize_t index = obj->number;
522 
523  if (list_obj->element_type != Py_TYPE (value))
524  return -1;
525 
526  if (!ptid_equal (list_obj->ptid, obj->ptid))
527  return -1;
528 
529  if (index < list_obj->first || index > list_obj->last)
530  return -1;
531 
532  index -= list_obj->first;
533 
534  if (index % list_obj->step != 0)
535  return -1;
536 
537  return index / list_obj->step;
538 }
539 
540 /* Implementation of "in" operator for BtraceLists. */
541 
542 static int
543 btpy_list_contains (PyObject *self, PyObject *value)
544 {
545  if (btpy_list_position (self, value) < 0)
546  return 0;
547 
548  return 1;
549 }
550 
551 /* Implementation of BtraceLists.index (self, value) -> int. */
552 
553 static PyObject *
554 btpy_list_index (PyObject *self, PyObject *value)
555 {
556  const LONGEST index = btpy_list_position (self, value);
557 
558  if (index < 0)
559  return PyErr_Format (PyExc_ValueError, _("Not in list."));
560 
561  return gdb_py_long_from_longest (index);
562 }
563 
564 /* Implementation of BtraceList.count (self, value) -> int. */
565 
566 static PyObject *
567 btpy_list_count (PyObject *self, PyObject *value)
568 {
569  /* We know that if an element is in the list, it is so exactly one time,
570  enabling us to reuse the "is element of" check. */
571  return PyInt_FromLong (btpy_list_contains (self, value));
572 }
573 
574 /* Python rich compare function to allow for equality and inequality checks
575  in Python. */
576 
577 static PyObject *
578 btpy_list_richcompare (PyObject *self, PyObject *other, int op)
579 {
580  const btpy_list_object * const obj1 = (btpy_list_object *) self;
581  const btpy_list_object * const obj2 = (btpy_list_object *) other;
582 
583  if (Py_TYPE (self) != Py_TYPE (other))
584  {
585  Py_INCREF (Py_NotImplemented);
586  return Py_NotImplemented;
587  }
588 
589  switch (op)
590  {
591  case Py_EQ:
592  if (ptid_equal (obj1->ptid, obj2->ptid)
593  && obj1->element_type == obj2->element_type
594  && obj1->first == obj2->first
595  && obj1->last == obj2->last
596  && obj1->step == obj2->step)
597  Py_RETURN_TRUE;
598  else
599  Py_RETURN_FALSE;
600 
601  case Py_NE:
602  if (!ptid_equal (obj1->ptid, obj2->ptid)
603  || obj1->element_type != obj2->element_type
604  || obj1->first != obj2->first
605  || obj1->last != obj2->last
606  || obj1->step != obj2->step)
607  Py_RETURN_TRUE;
608  else
609  Py_RETURN_FALSE;
610 
611  default:
612  break;
613  }
614 
615  Py_INCREF (Py_NotImplemented);
616  return Py_NotImplemented;
617 }
618 
619 /* Implementation of
620  BtraceRecord.method [str]. */
621 
622 PyObject *
623 recpy_bt_method (PyObject *self, void *closure)
624 {
625  return PyString_FromString ("btrace");
626 }
627 
628 /* Implementation of
629  BtraceRecord.format [str]. */
630 
631 PyObject *
632 recpy_bt_format (PyObject *self, void *closure)
633 {
634  const recpy_record_object * const record = (recpy_record_object *) self;
635  const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
636  const struct btrace_config * config;
637 
638  if (tinfo == NULL)
639  Py_RETURN_NONE;
640 
641  config = btrace_conf (&tinfo->btrace);
642 
643  if (config == NULL)
644  Py_RETURN_NONE;
645 
646  return PyString_FromString (btrace_format_short_string (config->format));
647 }
648 
649 /* Implementation of
650  BtraceRecord.replay_position [BtraceInstruction]. */
651 
652 PyObject *
653 recpy_bt_replay_position (PyObject *self, void *closure)
654 {
655  const recpy_record_object * const record = (recpy_record_object *) self;
656  const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
657 
658  if (tinfo == NULL)
659  Py_RETURN_NONE;
660 
661  if (tinfo->btrace.replay == NULL)
662  Py_RETURN_NONE;
663 
664  return btpy_insn_or_gap_new (tinfo,
665  btrace_insn_number (tinfo->btrace.replay));
666 }
667 
668 /* Implementation of
669  BtraceRecord.begin [BtraceInstruction]. */
670 
671 PyObject *
672 recpy_bt_begin (PyObject *self, void *closure)
673 {
674  const recpy_record_object * const record = (recpy_record_object *) self;
675  struct thread_info * const tinfo = find_thread_ptid (record->ptid);
676  struct btrace_insn_iterator iterator;
677 
678  if (tinfo == NULL)
679  Py_RETURN_NONE;
680 
681  btrace_fetch (tinfo);
682 
683  if (btrace_is_empty (tinfo))
684  Py_RETURN_NONE;
685 
686  btrace_insn_begin (&iterator, &tinfo->btrace);
687  return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
688 }
689 
690 /* Implementation of
691  BtraceRecord.end [BtraceInstruction]. */
692 
693 PyObject *
694 recpy_bt_end (PyObject *self, void *closure)
695 {
696  const recpy_record_object * const record = (recpy_record_object *) self;
697  struct thread_info * const tinfo = find_thread_ptid (record->ptid);
698  struct btrace_insn_iterator iterator;
699 
700  if (tinfo == NULL)
701  Py_RETURN_NONE;
702 
703  btrace_fetch (tinfo);
704 
705  if (btrace_is_empty (tinfo))
706  Py_RETURN_NONE;
707 
708  btrace_insn_end (&iterator, &tinfo->btrace);
709  return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
710 }
711 
712 /* Implementation of
713  BtraceRecord.instruction_history [list]. */
714 
715 PyObject *
716 recpy_bt_instruction_history (PyObject *self, void *closure)
717 {
718  const recpy_record_object * const record = (recpy_record_object *) self;
719  struct thread_info * const tinfo = find_thread_ptid (record->ptid);
720  struct btrace_insn_iterator iterator;
721  unsigned long first = 0;
722  unsigned long last = 0;
723 
724  if (tinfo == NULL)
725  Py_RETURN_NONE;
726 
727  btrace_fetch (tinfo);
728 
729  if (btrace_is_empty (tinfo))
730  Py_RETURN_NONE;
731 
732  btrace_insn_begin (&iterator, &tinfo->btrace);
733  first = btrace_insn_number (&iterator);
734 
735  btrace_insn_end (&iterator, &tinfo->btrace);
736  last = btrace_insn_number (&iterator);
737 
738  return btpy_list_new (record->ptid, first, last, 1, &recpy_insn_type);
739 }
740 
741 /* Implementation of
742  BtraceRecord.function_call_history [list]. */
743 
744 PyObject *
745 recpy_bt_function_call_history (PyObject *self, void *closure)
746 {
747  const recpy_record_object * const record = (recpy_record_object *) self;
748  struct thread_info * const tinfo = find_thread_ptid (record->ptid);
749  struct btrace_call_iterator iterator;
750  unsigned long first = 0;
751  unsigned long last = 0;
752 
753  if (tinfo == NULL)
754  Py_RETURN_NONE;
755 
756  btrace_fetch (tinfo);
757 
758  if (btrace_is_empty (tinfo))
759  Py_RETURN_NONE;
760 
761  btrace_call_begin (&iterator, &tinfo->btrace);
762  first = btrace_call_number (&iterator);
763 
764  btrace_call_end (&iterator, &tinfo->btrace);
765  last = btrace_call_number (&iterator);
766 
767  return btpy_list_new (record->ptid, first, last, 1, &recpy_func_type);
768 }
769 
770 /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
771 
772 PyObject *
773 recpy_bt_goto (PyObject *self, PyObject *args)
774 {
775  const recpy_record_object * const record = (recpy_record_object *) self;
776  struct thread_info * const tinfo = find_thread_ptid (record->ptid);
777  const recpy_element_object *obj;
778 
779  if (tinfo == NULL || btrace_is_empty (tinfo))
780  return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));
781 
782  if (!PyArg_ParseTuple (args, "O", &obj))
783  return NULL;
784 
785  if (Py_TYPE (obj) != &recpy_insn_type)
786  return PyErr_Format (PyExc_TypeError, _("Argument must be instruction."));
787 
788  TRY
789  {
790  struct btrace_insn_iterator iter;
791 
792  btrace_insn_end (&iter, &tinfo->btrace);
793 
794  if (btrace_insn_number (&iter) == obj->number)
796  else
797  target_goto_record (obj->number);
798  }
799  CATCH (except, RETURN_MASK_ALL)
800  {
801  GDB_PY_HANDLE_EXCEPTION (except);
802  }
803  END_CATCH
804 
805  Py_RETURN_NONE;
806 }
807 
808 /* BtraceList methods. */
809 
810 struct PyMethodDef btpy_list_methods[] =
811 {
812  { "count", btpy_list_count, METH_O, "count number of occurences"},
813  { "index", btpy_list_index, METH_O, "index of entry"},
814  {NULL}
815 };
816 
817 /* BtraceList sequence methods. */
818 
819 static PySequenceMethods btpy_list_sequence_methods =
820 {
821  NULL
822 };
823 
824 /* BtraceList mapping methods. Necessary for slicing. */
825 
826 static PyMappingMethods btpy_list_mapping_methods =
827 {
828  NULL
829 };
830 
831 /* Sets up the btrace record API. */
832 
833 int
835 {
836  btpy_list_type.tp_new = PyType_GenericNew;
837  btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
838  btpy_list_type.tp_basicsize = sizeof (btpy_list_object);
839  btpy_list_type.tp_name = "gdb.BtraceObjectList";
840  btpy_list_type.tp_doc = "GDB btrace list object";
841  btpy_list_type.tp_methods = btpy_list_methods;
842  btpy_list_type.tp_as_sequence = &btpy_list_sequence_methods;
843  btpy_list_type.tp_as_mapping = &btpy_list_mapping_methods;
844  btpy_list_type.tp_richcompare = btpy_list_richcompare;
845 
849 
851 
852  return PyType_Ready (&btpy_list_type);
853 }
Py_ssize_t number
Definition: py-record.h:53
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5467
struct thread_info * find_thread_ptid(ptid_t ptid)
Definition: thread.c:514
PyObject * symtab_and_line_to_sal_object(struct symtab_and_line sal)
Definition: py-symtab.c:438
PyObject * recpy_bt_func_symbol(PyObject *self, void *closure)
static PySequenceMethods btpy_list_sequence_methods
PyObject * recpy_insn_new(ptid_t ptid, enum record_method method, Py_ssize_t number)
Definition: py-record.c:179
void xfree(void *)
PyTypeObject * element_type
PyObject * recpy_bt_func_instructions(PyObject *self, void *closure)
void(* func)(char *)
def record(name, number, comment=None)
Definition: arm-linux.py:35
PyObject * recpy_bt_insn_size(PyObject *self, void *closure)
PyObject * recpy_bt_func_up(PyObject *self, void *closure)
unsigned int btrace_call_number(const struct btrace_call_iterator *it)
Definition: btrace.c:2630
static Py_ssize_t btpy_list_length(PyObject *self)
#define gdb_py_long_from_ulongest
static PyObject * btpy_list_index(PyObject *self, PyObject *value)
PyObject * recpy_bt_insn_pc(PyObject *self, void *closure)
int btrace_insn_get_error(const struct btrace_insn_iterator *it)
Definition: btrace.c:2340
PyObject * recpy_bt_instruction_history(PyObject *self, void *closure)
PyObject * recpy_bt_insn_is_speculative(PyObject *self, void *closure)
#define _(String)
Definition: gdb_locale.h:35
#define PyVarObject_HEAD_INIT(type, size)
void btrace_insn_begin(struct btrace_insn_iterator *it, const struct btrace_thread_info *btinfo)
Definition: btrace.c:2356
#define END_CATCH
static PyTypeObject btpy_list_type
static PyObject * btpy_list_item(PyObject *self, Py_ssize_t index)
PyObject * recpy_bt_format(PyObject *self, void *closure)
#define GDB_PY_HANDLE_EXCEPTION(Exception)
unsigned int btrace_insn_number(const struct btrace_insn_iterator *it)
Definition: btrace.c:2348
int gdbpy_initialize_btrace(void)
#define TRY
PyTypeObject recpy_func_type
Definition: py-record.c:41
static PyObject * btpy_list_slice(PyObject *self, PyObject *value)
#define CATCH(EXCEPTION, MASK)
PyObject * recpy_bt_begin(PyObject *self, void *closure)
struct symtab_and_line find_pc_line(CORE_ADDR pc, int notcurrent)
Definition: symtab.c:3288
PyObject * gdbpy_gdb_error
Definition: python.c:131
void btrace_insn_end(struct btrace_insn_iterator *it, const struct btrace_thread_info *btinfo)
Definition: btrace.c:2370
Definition: ptid.h:35
int gdb_print_insn(struct gdbarch *gdbarch, CORE_ADDR memaddr, struct ui_file *stream, int *branch_delay_insns)
Definition: disasm.c:813
PyObject * recpy_func_new(ptid_t ptid, enum record_method method, Py_ssize_t number)
Definition: py-record.c:275
static PyObject * btpy_insn_or_gap_new(const thread_info *tinfo, Py_ssize_t number)
#define BTPY_PYSLICE(x)
void btrace_call_end(struct btrace_call_iterator *it, const struct btrace_thread_info *btinfo)
Definition: btrace.c:2658
const char * btrace_decode_error(enum btrace_format format, int errcode)
Definition: btrace.c:1829
void target_goto_record_end(void)
Definition: target.c:3682
const struct btrace_config * btrace_conf(const struct btrace_thread_info *btinfo)
Definition: btrace.c:1625
const struct btrace_insn * btrace_insn_get(const struct btrace_insn_iterator *it)
Definition: btrace.c:2317
ptid_t ptid
Definition: gdbthread.h:219
void target_goto_record(ULONGEST insn)
Definition: target.c:3690
PyObject * recpy_bt_goto(PyObject *self, PyObject *args)
void read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition: corefile.c:258
void * xmalloc(YYSIZE_T)
static PyObject * btpy_list_richcompare(PyObject *self, PyObject *other, int op)
CORE_ADDR pc
Definition: btrace.h:72
PyObject * recpy_bt_func_level(PyObject *self, void *closure)
std::string & string()
Definition: ui-file.h:132
Definition: value.c:169
int btrace_is_empty(struct thread_info *tp)
Definition: btrace.c:2806
#define gdb_py_long_from_longest
btrace_insn_flags flags
Definition: btrace.h:81
static PyObject * btpy_list_count(PyObject *self, PyObject *value)
PyObject * recpy_bt_func_prev(PyObject *self, void *closure)
static int btpy_list_contains(PyObject *self, PyObject *value)
bfd_byte gdb_byte
Definition: common-types.h:38
void btrace_fetch(struct thread_info *tp)
Definition: btrace.c:1878
static const btrace_function * btrace_func_from_recpy_func(const PyObject *const pyobject)
PyObject * recpy_bt_replay_position(PyObject *self, void *closure)
static const btrace_insn * btrace_insn_from_recpy_insn(const PyObject *const pyobject)
void btrace_call_begin(struct btrace_call_iterator *it, const struct btrace_thread_info *btinfo)
Definition: btrace.c:2645
void gdbpy_convert_exception(struct gdb_exception exception)
Definition: py-utils.c:235
PyObject * recpy_bt_method(PyObject *self, void *closure)
PyObject_HEAD ptid_t ptid
Definition: buffer.h:23
const struct btrace_function * btrace_call_get(const struct btrace_call_iterator *it)
Definition: btrace.c:2619
int ptid_equal(const ptid_t &ptid1, const ptid_t &ptid2)
Definition: ptid.c:71
PyObject * recpy_bt_insn_sal(PyObject *self, void *closure)
static LONGEST btpy_list_position(PyObject *self, PyObject *value)
PyObject * recpy_gap_new(int reason_code, const char *reason_string, Py_ssize_t number)
Definition: py-record.c:434
PyObject_HEAD ptid_t ptid
Definition: py-record.h:47
PyTypeObject recpy_insn_type
Definition: py-record.c:35
static PyMappingMethods btpy_list_mapping_methods
#define Py_TYPE(ob)
gdb_byte size
Definition: btrace.h:75
int btrace_find_insn_by_number(struct btrace_insn_iterator *it, const struct btrace_thread_info *btinfo, unsigned int number)
Definition: btrace.c:2550
enum btrace_format format
PyObject * recpy_bt_insn_decoded(PyObject *self, void *closure)
PyObject * recpy_bt_insn_data(PyObject *self, void *closure)
PyObject * symbol_to_symbol_object(struct symbol *sym)
Definition: py-symbol.c:325
PyObject * recpy_bt_end(PyObject *self, void *closure)
struct PyMethodDef btpy_list_methods[]
PyObject * recpy_bt_func_next(PyObject *self, void *closure)
PyObject * recpy_bt_function_call_history(PyObject *self, void *closure)
int btrace_find_call_by_number(struct btrace_call_iterator *it, const struct btrace_thread_info *btinfo, unsigned int number)
Definition: btrace.c:2751
const char * btrace_format_short_string(enum btrace_format format)
Definition: btrace-common.c:47
static PyObject * btpy_list_new(ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step, PyTypeObject *element_type)
long long LONGEST
Definition: common-types.h:52