]> Git Repo - binutils.git/blob - gdb/python/py-record-btrace.c
Make it simpler to add events to Python
[binutils.git] / gdb / python / py-record-btrace.c
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.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.  */
45   ptid_t ptid;
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;
58 } btpy_list_object;
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;
75   btrace_insn_iterator iter;
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;
118   btrace_call_iterator iter;
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 {
157   btrace_insn_iterator iter;
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
262   if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
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,
405                          RECORD_METHOD_BTRACE, func->up);
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   struct thread_info * const tinfo = find_thread_ptid (obj->ptid);
468   Py_ssize_t number;
469
470   if (index < 0 || index >= btpy_list_length (self))
471     return PyErr_Format (PyExc_IndexError, _("Index out of range: %zd."),
472                          index);
473
474   number = obj->first + (obj->step * index);
475
476   if (obj->element_type == &recpy_insn_type)
477     return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number);
478   else
479     return recpy_func_new (obj->ptid, RECORD_METHOD_BTRACE, number);
480 }
481
482 /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList.  */
483
484 static PyObject *
485 btpy_list_slice (PyObject *self, PyObject *value)
486 {
487   const btpy_list_object * const obj = (btpy_list_object *) self;
488   const Py_ssize_t length = btpy_list_length (self);
489   Py_ssize_t start, stop, step, slicelength;
490
491   if (PyInt_Check (value))
492     {
493       Py_ssize_t index = PyInt_AsSsize_t (value);
494
495       /* Emulate Python behavior for negative indices.  */
496       if (index < 0)
497         index += length;
498
499       return btpy_list_item (self, index);
500     }
501
502   if (!PySlice_Check (value))
503     return PyErr_Format (PyExc_TypeError, _("Index must be int or slice."));
504
505   if (0 != PySlice_GetIndicesEx (BTPY_PYSLICE (value), length, &start, &stop,
506                                  &step, &slicelength))
507     return NULL;
508
509   return btpy_list_new (obj->ptid, obj->first + obj->step * start,
510                         obj->first + obj->step * stop, obj->step * step,
511                         obj->element_type);
512 }
513
514 /* Helper function that returns the position of an element in a BtraceList
515    or -1 if the element is not in the list.  */
516
517 static LONGEST
518 btpy_list_position (PyObject *self, PyObject *value)
519 {
520   const btpy_list_object * const list_obj = (btpy_list_object *) self;
521   const recpy_element_object * const obj = (const recpy_element_object *) value;
522   Py_ssize_t index = obj->number;
523
524   if (list_obj->element_type != Py_TYPE (value))
525     return -1;
526
527   if (!ptid_equal (list_obj->ptid, obj->ptid))
528     return -1;
529
530   if (index < list_obj->first || index > list_obj->last)
531     return -1;
532
533   index -= list_obj->first;
534
535   if (index % list_obj->step != 0)
536     return -1;
537
538   return index / list_obj->step;
539 }
540
541 /* Implementation of "in" operator for BtraceLists.  */
542
543 static int
544 btpy_list_contains (PyObject *self, PyObject *value)
545 {
546   if (btpy_list_position (self, value) < 0)
547     return 0;
548
549   return 1;
550 }
551
552 /* Implementation of BtraceLists.index (self, value) -> int.  */
553
554 static PyObject *
555 btpy_list_index (PyObject *self, PyObject *value)
556 {
557   const LONGEST index = btpy_list_position (self, value);
558
559   if (index < 0)
560     return PyErr_Format (PyExc_ValueError, _("Not in list."));
561
562   return gdb_py_long_from_longest (index);
563 }
564
565 /* Implementation of BtraceList.count (self, value) -> int.  */
566
567 static PyObject *
568 btpy_list_count (PyObject *self, PyObject *value)
569 {
570   /* We know that if an element is in the list, it is so exactly one time,
571      enabling us to reuse the "is element of" check.  */
572   return PyInt_FromLong (btpy_list_contains (self, value));
573 }
574
575 /* Python rich compare function to allow for equality and inequality checks
576    in Python.  */
577
578 static PyObject *
579 btpy_list_richcompare (PyObject *self, PyObject *other, int op)
580 {
581   const btpy_list_object * const obj1 = (btpy_list_object *) self;
582   const btpy_list_object * const obj2 = (btpy_list_object *) other;
583
584   if (Py_TYPE (self) != Py_TYPE (other))
585     {
586       Py_INCREF (Py_NotImplemented);
587       return Py_NotImplemented;
588     }
589
590   switch (op)
591   {
592     case Py_EQ:
593       if (ptid_equal (obj1->ptid, obj2->ptid)
594           && obj1->element_type == obj2->element_type
595           && obj1->first == obj2->first
596           && obj1->last == obj2->last
597           && obj1->step == obj2->step)
598         Py_RETURN_TRUE;
599       else
600         Py_RETURN_FALSE;
601
602     case Py_NE:
603       if (!ptid_equal (obj1->ptid, obj2->ptid)
604           || obj1->element_type != obj2->element_type
605           || obj1->first != obj2->first
606           || obj1->last != obj2->last
607           || obj1->step != obj2->step)
608         Py_RETURN_TRUE;
609       else
610         Py_RETURN_FALSE;
611
612     default:
613       break;
614   }
615
616   Py_INCREF (Py_NotImplemented);
617   return Py_NotImplemented;
618 }
619
620 /* Implementation of
621    BtraceRecord.method [str].  */
622
623 PyObject *
624 recpy_bt_method (PyObject *self, void *closure)
625 {
626   return PyString_FromString ("btrace");
627 }
628
629 /* Implementation of
630    BtraceRecord.format [str].  */
631
632 PyObject *
633 recpy_bt_format (PyObject *self, void *closure)
634 {
635   const recpy_record_object * const record = (recpy_record_object *) self;
636   const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
637   const struct btrace_config * config;
638
639   if (tinfo == NULL)
640     Py_RETURN_NONE;
641
642   config = btrace_conf (&tinfo->btrace);
643
644   if (config == NULL)
645     Py_RETURN_NONE;
646
647   return PyString_FromString (btrace_format_short_string (config->format));
648 }
649
650 /* Implementation of
651    BtraceRecord.replay_position [BtraceInstruction].  */
652
653 PyObject *
654 recpy_bt_replay_position (PyObject *self, void *closure)
655 {
656   const recpy_record_object * const record = (recpy_record_object *) self;
657   const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
658
659   if (tinfo == NULL)
660     Py_RETURN_NONE;
661
662   if (tinfo->btrace.replay == NULL)
663     Py_RETURN_NONE;
664
665   return btpy_insn_or_gap_new (tinfo,
666                                btrace_insn_number (tinfo->btrace.replay));
667 }
668
669 /* Implementation of
670    BtraceRecord.begin [BtraceInstruction].  */
671
672 PyObject *
673 recpy_bt_begin (PyObject *self, void *closure)
674 {
675   const recpy_record_object * const record = (recpy_record_object *) self;
676   struct thread_info * const tinfo = find_thread_ptid (record->ptid);
677   struct btrace_insn_iterator iterator;
678
679   if (tinfo == NULL)
680     Py_RETURN_NONE;
681
682   btrace_fetch (tinfo);
683
684   if (btrace_is_empty (tinfo))
685     Py_RETURN_NONE;
686
687   btrace_insn_begin (&iterator, &tinfo->btrace);
688   return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
689 }
690
691 /* Implementation of
692    BtraceRecord.end [BtraceInstruction].  */
693
694 PyObject *
695 recpy_bt_end (PyObject *self, void *closure)
696 {
697   const recpy_record_object * const record = (recpy_record_object *) self;
698   struct thread_info * const tinfo = find_thread_ptid (record->ptid);
699   struct btrace_insn_iterator iterator;
700
701   if (tinfo == NULL)
702     Py_RETURN_NONE;
703
704   btrace_fetch (tinfo);
705
706   if (btrace_is_empty (tinfo))
707     Py_RETURN_NONE;
708
709   btrace_insn_end (&iterator, &tinfo->btrace);
710   return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
711 }
712
713 /* Implementation of
714    BtraceRecord.instruction_history [list].  */
715
716 PyObject *
717 recpy_bt_instruction_history (PyObject *self, void *closure)
718 {
719   const recpy_record_object * const record = (recpy_record_object *) self;
720   struct thread_info * const tinfo = find_thread_ptid (record->ptid);
721   struct btrace_insn_iterator iterator;
722   unsigned long first = 0;
723   unsigned long last = 0;
724
725    if (tinfo == NULL)
726      Py_RETURN_NONE;
727
728    btrace_fetch (tinfo);
729
730    if (btrace_is_empty (tinfo))
731      Py_RETURN_NONE;
732
733    btrace_insn_begin (&iterator, &tinfo->btrace);
734    first = btrace_insn_number (&iterator);
735
736    btrace_insn_end (&iterator, &tinfo->btrace);
737    last = btrace_insn_number (&iterator);
738
739    return btpy_list_new (record->ptid, first, last, 1, &recpy_insn_type);
740 }
741
742 /* Implementation of
743    BtraceRecord.function_call_history [list].  */
744
745 PyObject *
746 recpy_bt_function_call_history (PyObject *self, void *closure)
747 {
748   const recpy_record_object * const record = (recpy_record_object *) self;
749   struct thread_info * const tinfo = find_thread_ptid (record->ptid);
750   struct btrace_call_iterator iterator;
751   unsigned long first = 0;
752   unsigned long last = 0;
753
754   if (tinfo == NULL)
755     Py_RETURN_NONE;
756
757   btrace_fetch (tinfo);
758
759   if (btrace_is_empty (tinfo))
760     Py_RETURN_NONE;
761
762   btrace_call_begin (&iterator, &tinfo->btrace);
763   first = btrace_call_number (&iterator);
764
765   btrace_call_end (&iterator, &tinfo->btrace);
766   last = btrace_call_number (&iterator);
767
768   return btpy_list_new (record->ptid, first, last, 1, &recpy_func_type);
769 }
770
771 /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None.  */
772
773 PyObject *
774 recpy_bt_goto (PyObject *self, PyObject *args)
775 {
776   const recpy_record_object * const record = (recpy_record_object *) self;
777   struct thread_info * const tinfo = find_thread_ptid (record->ptid);
778   const recpy_element_object *obj;
779
780   if (tinfo == NULL || btrace_is_empty (tinfo))
781         return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));
782
783   if (!PyArg_ParseTuple (args, "O", &obj))
784     return NULL;
785
786   if (Py_TYPE (obj) != &recpy_insn_type)
787     return PyErr_Format (PyExc_TypeError, _("Argument must be instruction."));
788
789   TRY
790     {
791       struct btrace_insn_iterator iter;
792
793       btrace_insn_end (&iter, &tinfo->btrace);
794
795       if (btrace_insn_number (&iter) == obj->number)
796         target_goto_record_end ();
797       else
798         target_goto_record (obj->number);
799     }
800   CATCH (except, RETURN_MASK_ALL)
801     {
802       GDB_PY_HANDLE_EXCEPTION (except);
803     }
804   END_CATCH
805
806   Py_RETURN_NONE;
807 }
808
809 /* BtraceList methods.  */
810
811 struct PyMethodDef btpy_list_methods[] =
812 {
813   { "count", btpy_list_count, METH_O, "count number of occurences"},
814   { "index", btpy_list_index, METH_O, "index of entry"},
815   {NULL}
816 };
817
818 /* BtraceList sequence methods.  */
819
820 static PySequenceMethods btpy_list_sequence_methods =
821 {
822   NULL
823 };
824
825 /* BtraceList mapping methods.  Necessary for slicing.  */
826
827 static PyMappingMethods btpy_list_mapping_methods =
828 {
829   NULL
830 };
831
832 /* Sets up the btrace record API.  */
833
834 int
835 gdbpy_initialize_btrace (void)
836 {
837   btpy_list_type.tp_new = PyType_GenericNew;
838   btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
839   btpy_list_type.tp_basicsize = sizeof (btpy_list_object);
840   btpy_list_type.tp_name = "gdb.BtraceObjectList";
841   btpy_list_type.tp_doc = "GDB btrace list object";
842   btpy_list_type.tp_methods = btpy_list_methods;
843   btpy_list_type.tp_as_sequence = &btpy_list_sequence_methods;
844   btpy_list_type.tp_as_mapping = &btpy_list_mapping_methods;
845   btpy_list_type.tp_richcompare = btpy_list_richcompare;
846
847   btpy_list_sequence_methods.sq_item = btpy_list_item;
848   btpy_list_sequence_methods.sq_length = btpy_list_length;
849   btpy_list_sequence_methods.sq_contains = btpy_list_contains;
850
851   btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
852
853   return PyType_Ready (&btpy_list_type);
854 }
This page took 0.071832 seconds and 4 git commands to generate.