]> Git Repo - binutils.git/blob - gdb/python/py-record-btrace.c
Let gdb.execute handle multi-line commands
[binutils.git] / gdb / python / py-record-btrace.c
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 "record-btrace.h"
28 #include "disasm.h"
29
30 #if defined (IS_PY3K)
31
32 #define BTPY_PYSLICE(x) (x)
33
34 #else
35
36 #define BTPY_PYSLICE(x) ((PySliceObject *) x)
37
38 #endif
39
40 /* Python object for btrace record lists.  */
41
42 typedef struct {
43   PyObject_HEAD
44
45   /* The thread this list belongs to.  */
46   ptid_t ptid;
47
48   /* The first index being part of this list.  */
49   Py_ssize_t first;
50
51   /* The last index begin part of this list.  */
52   Py_ssize_t last;
53
54   /* Stride size.  */
55   Py_ssize_t step;
56
57   /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE.  */
58   PyTypeObject* element_type;
59 } btpy_list_object;
60
61 /* Python type for btrace lists.  */
62
63 static PyTypeObject btpy_list_type = {
64   PyVarObject_HEAD_INIT (NULL, 0)
65 };
66
67 /* Returns either a btrace_insn for the given Python gdb.RecordInstruction
68    object or sets an appropriate Python exception and returns NULL.  */
69
70 static const btrace_insn *
71 btrace_insn_from_recpy_insn (const PyObject * const pyobject)
72 {
73   const btrace_insn *insn;
74   const recpy_element_object *obj;
75   thread_info *tinfo;
76   btrace_insn_iterator iter;
77
78   if (Py_TYPE (pyobject) != &recpy_insn_type)
79     {
80       PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordInstruction"));
81       return NULL;
82     }
83
84   obj = (const recpy_element_object *) pyobject;
85   tinfo = find_thread_ptid (obj->ptid);
86
87   if (tinfo == NULL || btrace_is_empty (tinfo))
88     {
89       PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
90       return NULL;
91     }
92
93   if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0)
94     {
95       PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
96       return NULL;
97     }
98
99   insn = btrace_insn_get (&iter);
100   if (insn == NULL)
101     {
102       PyErr_Format (gdbpy_gdb_error, _("Not a valid instruction."));
103       return NULL;
104     }
105
106   return insn;
107 }
108
109 /* Returns either a btrace_function for the given Python
110    gdb.RecordFunctionSegment object or sets an appropriate Python exception and
111    returns NULL.  */
112
113 static const btrace_function *
114 btrace_func_from_recpy_func (const PyObject * const pyobject)
115 {
116   const btrace_function *func;
117   const recpy_element_object *obj;
118   thread_info *tinfo;
119   btrace_call_iterator iter;
120
121   if (Py_TYPE (pyobject) != &recpy_func_type)
122     {
123       PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordFunctionSegment"));
124       return NULL;
125     }
126
127   obj = (const recpy_element_object *) pyobject;
128   tinfo = find_thread_ptid (obj->ptid);
129
130   if (tinfo == NULL || btrace_is_empty (tinfo))
131     {
132       PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
133       return NULL;
134     }
135
136   if (btrace_find_call_by_number (&iter, &tinfo->btrace, obj->number) == 0)
137     {
138       PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
139       return NULL;
140     }
141
142   func = btrace_call_get (&iter);
143   if (func == NULL)
144     {
145       PyErr_Format (gdbpy_gdb_error, _("Not a valid function segment."));
146       return NULL;
147     }
148
149   return func;
150 }
151
152 /* Looks at the recorded item with the number NUMBER and create a
153    gdb.RecordInstruction or gdb.RecordGap object for it accordingly.  */
154
155 static PyObject *
156 btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
157 {
158   btrace_insn_iterator iter;
159   int err_code;
160
161   btrace_find_insn_by_number (&iter, &tinfo->btrace, number);
162   err_code = btrace_insn_get_error (&iter);
163
164   if (err_code != 0)
165     {
166       const btrace_config *config;
167       const char *err_string;
168
169       config = btrace_conf (&tinfo->btrace);
170       err_string = btrace_decode_error (config->format, err_code);
171
172       return recpy_gap_new (err_code, err_string, number);
173     }
174
175   return recpy_insn_new (tinfo->ptid, RECORD_METHOD_BTRACE, number);
176 }
177
178 /* Create a new gdb.BtraceList object.  */
179
180 static PyObject *
181 btpy_list_new (ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step,
182                PyTypeObject *element_type)
183 {
184   btpy_list_object * const obj = PyObject_New (btpy_list_object,
185                                                &btpy_list_type);
186
187   if (obj == NULL)
188     return NULL;
189
190   obj->ptid = ptid;
191   obj->first = first;
192   obj->last = last;
193   obj->step = step;
194   obj->element_type = element_type;
195
196   return (PyObject *) obj;
197 }
198
199 /* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
200    Returns the SAL associated with this instruction.  */
201
202 PyObject *
203 recpy_bt_insn_sal (PyObject *self, void *closure)
204 {
205   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
206   PyObject *result = NULL;
207
208   if (insn == NULL)
209     return NULL;
210
211   TRY
212     {
213       result = symtab_and_line_to_sal_object (find_pc_line (insn->pc, 0));
214     }
215   CATCH (except, RETURN_MASK_ALL)
216     {
217       GDB_PY_HANDLE_EXCEPTION (except);
218     }
219   END_CATCH
220
221   return result;
222 }
223
224 /* Implementation of RecordInstruction.pc [int] for btrace.
225    Returns the instruction address.  */
226
227 PyObject *
228 recpy_bt_insn_pc (PyObject *self, void *closure)
229 {
230   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
231
232   if (insn == NULL)
233     return NULL;
234
235   return gdb_py_long_from_ulongest (insn->pc);
236 }
237
238 /* Implementation of RecordInstruction.size [int] for btrace.
239    Returns the instruction size.  */
240
241 PyObject *
242 recpy_bt_insn_size (PyObject *self, void *closure)
243 {
244   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
245
246   if (insn == NULL)
247     return NULL;
248
249   return PyInt_FromLong (insn->size);
250 }
251
252 /* Implementation of RecordInstruction.is_speculative [bool] for btrace.
253    Returns if this instruction was executed speculatively.  */
254
255 PyObject *
256 recpy_bt_insn_is_speculative (PyObject *self, void *closure)
257 {
258   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
259
260   if (insn == NULL)
261     return NULL;
262
263   if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
264     Py_RETURN_TRUE;
265   else
266     Py_RETURN_FALSE;
267 }
268
269 /* Implementation of RecordInstruction.data [buffer] for btrace.
270    Returns raw instruction data.  */
271
272 PyObject *
273 recpy_bt_insn_data (PyObject *self, void *closure)
274 {
275   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
276   gdb_byte *buffer = NULL;
277   PyObject *object;
278
279   if (insn == NULL)
280     return NULL;
281
282   TRY
283     {
284       buffer = (gdb_byte *) xmalloc (insn->size);
285       read_memory (insn->pc, buffer, insn->size);
286     }
287   CATCH (except, RETURN_MASK_ALL)
288     {
289       xfree (buffer);
290       GDB_PY_HANDLE_EXCEPTION (except);
291     }
292   END_CATCH
293
294   object = PyBytes_FromStringAndSize ((const char*) buffer, insn->size);
295   xfree (buffer);
296
297   if (object == NULL)
298     return NULL;
299
300 #ifdef IS_PY3K
301   return PyMemoryView_FromObject (object);
302 #else
303   return PyBuffer_FromObject (object, 0, Py_END_OF_BUFFER);
304 #endif
305
306 }
307
308 /* Implementation of RecordInstruction.decoded [str] for btrace.
309    Returns the instruction as human readable string.  */
310
311 PyObject *
312 recpy_bt_insn_decoded (PyObject *self, void *closure)
313 {
314   const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
315   string_file strfile;
316
317   if (insn == NULL)
318     return NULL;
319
320   TRY
321     {
322       gdb_print_insn (target_gdbarch (), insn->pc, &strfile, NULL);
323     }
324   CATCH (except, RETURN_MASK_ALL)
325     {
326       gdbpy_convert_exception (except);
327       return NULL;
328     }
329   END_CATCH
330
331
332   return PyBytes_FromString (strfile.string ().c_str ());
333 }
334
335 /* Implementation of RecordFunctionSegment.level [int] for btrace.
336    Returns the call level.  */
337
338 PyObject *
339 recpy_bt_func_level (PyObject *self, void *closure)
340 {
341   const btrace_function * const func = btrace_func_from_recpy_func (self);
342   thread_info *tinfo;
343
344   if (func == NULL)
345     return NULL;
346
347   tinfo = find_thread_ptid (((recpy_element_object *) self)->ptid);
348   return PyInt_FromLong (tinfo->btrace.level + func->level);
349 }
350
351 /* Implementation of RecordFunctionSegment.symbol [gdb.Symbol] for btrace.
352    Returns the symbol associated with this function call.  */
353
354 PyObject *
355 recpy_bt_func_symbol (PyObject *self, void *closure)
356 {
357   const btrace_function * const func = btrace_func_from_recpy_func (self);
358
359   if (func == NULL)
360     return NULL;
361
362   if (func->sym == NULL)
363     Py_RETURN_NONE;
364
365   return symbol_to_symbol_object (func->sym);
366 }
367
368 /* Implementation of RecordFunctionSegment.instructions [list] for btrace.
369    Returns the list of instructions that belong to this function call.  */
370
371 PyObject *
372 recpy_bt_func_instructions (PyObject *self, void *closure)
373 {
374   const btrace_function * const func = btrace_func_from_recpy_func (self);
375   unsigned int len;
376
377   if (func == NULL)
378     return NULL;
379
380   len = func->insn.size ();
381
382   /* Gaps count as one instruction.  */
383   if (len == 0)
384     len = 1;
385
386   return btpy_list_new (((recpy_element_object *) self)->ptid,
387                         func->insn_offset, func->insn_offset + len, 1,
388                         &recpy_insn_type);
389 }
390
391 /* Implementation of RecordFunctionSegment.up [RecordFunctionSegment] for
392    btrace.  Returns the caller / returnee of this function.  */
393
394 PyObject *
395 recpy_bt_func_up (PyObject *self, void *closure)
396 {
397   const btrace_function * const func = btrace_func_from_recpy_func (self);
398
399   if (func == NULL)
400     return NULL;
401
402   if (func->up == 0)
403     Py_RETURN_NONE;
404
405   return recpy_func_new (((recpy_element_object *) self)->ptid,
406                          RECORD_METHOD_BTRACE, func->up);
407 }
408
409 /* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment] for
410    btrace.  Returns a previous segment of this function.  */
411
412 PyObject *
413 recpy_bt_func_prev (PyObject *self, void *closure)
414 {
415   const btrace_function * const func = btrace_func_from_recpy_func (self);
416
417   if (func == NULL)
418     return NULL;
419
420   if (func->prev == 0)
421     Py_RETURN_NONE;
422
423   return recpy_func_new (((recpy_element_object *) self)->ptid,
424                          RECORD_METHOD_BTRACE, func->prev);
425 }
426
427 /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
428    btrace.  Returns a following segment of this function.  */
429
430 PyObject *
431 recpy_bt_func_next (PyObject *self, void *closure)
432 {
433   const btrace_function * const func = btrace_func_from_recpy_func (self);
434
435   if (func == NULL)
436     return NULL;
437
438   if (func->next == 0)
439     Py_RETURN_NONE;
440
441   return recpy_func_new (((recpy_element_object *) self)->ptid,
442                          RECORD_METHOD_BTRACE, func->next);
443 }
444
445 /* Implementation of BtraceList.__len__ (self) -> int.  */
446
447 static Py_ssize_t
448 btpy_list_length (PyObject *self)
449 {
450   const btpy_list_object * const obj = (btpy_list_object *) self;
451   const Py_ssize_t distance = obj->last - obj->first;
452   const Py_ssize_t result = distance / obj->step;
453
454   if ((distance % obj->step) == 0)
455     return result;
456
457   return result + 1;
458 }
459
460 /* Implementation of
461    BtraceList.__getitem__ (self, key) -> BtraceInstruction and
462    BtraceList.__getitem__ (self, key) -> BtraceFunctionCall.  */
463
464 static PyObject *
465 btpy_list_item (PyObject *self, Py_ssize_t index)
466 {
467   const btpy_list_object * const obj = (btpy_list_object *) self;
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, record_btrace_get_cpu ());
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, record_btrace_get_cpu ());
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, record_btrace_get_cpu ());
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, record_btrace_get_cpu ());
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.0745 seconds and 4 git commands to generate.