Python: Move and rename gdb.BtraceFunction
[deliverable/binutils-gdb.git] / gdb / python / py-record.c
CommitLineData
4726b2d8
TW
1/* Python interface to record targets.
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"
ae20e79a 21#include "py-record.h"
75c0bdf4
TW
22#include "py-record-btrace.h"
23#include "py-record-full.h"
4726b2d8
TW
24#include "target.h"
25
4726b2d8
TW
26/* Python Record type. */
27
28static PyTypeObject recpy_record_type = {
29 PyVarObject_HEAD_INIT (NULL, 0)
30};
31
0ed5da75
TW
32/* Python RecordInstruction type. */
33
34PyTypeObject recpy_insn_type = {
35 PyVarObject_HEAD_INIT (NULL, 0)
36};
37
14f819c8
TW
38/* Python RecordFunctionSegment type. */
39
40PyTypeObject recpy_func_type = {
41 PyVarObject_HEAD_INIT (NULL, 0)
42};
43
913aeadd
TW
44/* Python RecordGap type. */
45
46PyTypeObject recpy_gap_type = {
47 PyVarObject_HEAD_INIT (NULL, 0)
48};
49
50/* Python RecordGap object. */
51typedef struct
52{
53 PyObject_HEAD
54
55 /* Reason code. */
56 int reason_code;
57
58 /* Reason message. */
59 const char *reason_string;
60
61 /* Element number. */
62 Py_ssize_t number;
63} recpy_gap_object;
64
4726b2d8
TW
65/* Implementation of record.method. */
66
67static PyObject *
68recpy_method (PyObject *self, void* closure)
69{
75c0bdf4
TW
70 const recpy_record_object * const obj = (recpy_record_object *) self;
71
72 if (obj->method == RECORD_METHOD_FULL)
73 return recpy_full_method (self, closure);
74
75 if (obj->method == RECORD_METHOD_BTRACE)
76 return recpy_bt_method (self, closure);
77
4726b2d8
TW
78 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
79}
80
81/* Implementation of record.format. */
82
83static PyObject *
84recpy_format (PyObject *self, void* closure)
85{
75c0bdf4
TW
86 const recpy_record_object * const obj = (recpy_record_object *) self;
87
88 if (obj->method == RECORD_METHOD_FULL)
89 return recpy_full_format (self, closure);
90
91 if (obj->method == RECORD_METHOD_BTRACE)
92 return recpy_bt_format (self, closure);
93
4726b2d8
TW
94 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
95}
96
97/* Implementation of record.goto (instruction) -> None. */
98
99static PyObject *
100recpy_goto (PyObject *self, PyObject *value)
101{
75c0bdf4
TW
102 const recpy_record_object * const obj = (recpy_record_object *) self;
103
104 if (obj->method == RECORD_METHOD_BTRACE)
105 return recpy_bt_goto (self, value);
106
4726b2d8
TW
107 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
108}
109
110/* Implementation of record.replay_position [instruction] */
111
112static PyObject *
113recpy_replay_position (PyObject *self, void *closure)
114{
75c0bdf4
TW
115 const recpy_record_object * const obj = (recpy_record_object *) self;
116
117 if (obj->method == RECORD_METHOD_BTRACE)
118 return recpy_bt_replay_position (self, closure);
119
4726b2d8
TW
120 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
121}
122
123/* Implementation of record.instruction_history [list]. */
124
125static PyObject *
126recpy_instruction_history (PyObject *self, void* closure)
127{
75c0bdf4
TW
128 const recpy_record_object * const obj = (recpy_record_object *) self;
129
130 if (obj->method == RECORD_METHOD_BTRACE)
131 return recpy_bt_instruction_history (self, closure);
132
4726b2d8
TW
133 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
134}
135
136/* Implementation of record.function_call_history [list]. */
137
138static PyObject *
139recpy_function_call_history (PyObject *self, void* closure)
140{
75c0bdf4
TW
141 const recpy_record_object * const obj = (recpy_record_object *) self;
142
143 if (obj->method == RECORD_METHOD_BTRACE)
144 return recpy_bt_function_call_history (self, closure);
145
4726b2d8
TW
146 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
147}
148
149/* Implementation of record.begin [instruction]. */
150
151static PyObject *
152recpy_begin (PyObject *self, void* closure)
153{
75c0bdf4
TW
154 const recpy_record_object * const obj = (recpy_record_object *) self;
155
156 if (obj->method == RECORD_METHOD_BTRACE)
157 return recpy_bt_begin (self, closure);
158
4726b2d8
TW
159 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
160}
161
162/* Implementation of record.end [instruction]. */
163
164static PyObject *
165recpy_end (PyObject *self, void* closure)
166{
75c0bdf4
TW
167 const recpy_record_object * const obj = (recpy_record_object *) self;
168
169 if (obj->method == RECORD_METHOD_BTRACE)
170 return recpy_bt_end (self, closure);
171
4726b2d8
TW
172 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
173}
174
0ed5da75
TW
175/* Create a new gdb.RecordInstruction object. */
176
177PyObject *
178recpy_insn_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
179{
180 recpy_element_object * const obj = PyObject_New (recpy_element_object,
181 &recpy_insn_type);
182
183 if (obj == NULL)
184 return NULL;
185
186 obj->ptid = ptid;
187 obj->method = method;
188 obj->number = number;
189
190 return (PyObject *) obj;
191}
192
193/* Implementation of RecordInstruction.sal [gdb.Symtab_and_line]. */
194
195static PyObject *
196recpy_insn_sal (PyObject *self, void *closure)
197{
198 const recpy_element_object * const obj = (recpy_element_object *) self;
199
200 if (obj->method == RECORD_METHOD_BTRACE)
201 return recpy_bt_insn_sal (self, closure);
202
203 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
204}
205
206/* Implementation of RecordInstruction.pc [int]. */
207
208static PyObject *
209recpy_insn_pc (PyObject *self, void *closure)
210{
211 const recpy_element_object * const obj = (recpy_element_object *) self;
212
213 if (obj->method == RECORD_METHOD_BTRACE)
214 return recpy_bt_insn_pc (self, closure);
215
216 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
217}
218
219/* Implementation of RecordInstruction.data [buffer]. */
220
221static PyObject *
222recpy_insn_data (PyObject *self, void *closure)
223{
224 const recpy_element_object * const obj = (recpy_element_object *) self;
225
226 if (obj->method == RECORD_METHOD_BTRACE)
227 return recpy_bt_insn_data (self, closure);
228
229 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
230}
231
232/* Implementation of RecordInstruction.decoded [str]. */
233
234static PyObject *
235recpy_insn_decoded (PyObject *self, void *closure)
236{
237 const recpy_element_object * const obj = (recpy_element_object *) self;
238
239 if (obj->method == RECORD_METHOD_BTRACE)
240 return recpy_bt_insn_decoded (self, closure);
241
242 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
243}
244
245/* Implementation of RecordInstruction.size [int]. */
246
247static PyObject *
248recpy_insn_size (PyObject *self, void *closure)
249{
250 const recpy_element_object * const obj = (recpy_element_object *) self;
251
252 if (obj->method == RECORD_METHOD_BTRACE)
253 return recpy_bt_insn_size (self, closure);
254
255 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
256}
257
258/* Implementation of RecordInstruction.is_speculative [bool]. */
259
260static PyObject *
261recpy_insn_is_speculative (PyObject *self, void *closure)
262{
263 const recpy_element_object * const obj = (recpy_element_object *) self;
264
265 if (obj->method == RECORD_METHOD_BTRACE)
266 return recpy_bt_insn_is_speculative (self, closure);
267
268 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
269}
270
14f819c8
TW
271/* Create a new gdb.RecordFunctionSegment object. */
272
273PyObject *
274recpy_func_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
275{
276 recpy_element_object * const obj = PyObject_New (recpy_element_object,
277 &recpy_func_type);
278
279 if (obj == NULL)
280 return NULL;
281
282 obj->ptid = ptid;
283 obj->method = method;
284 obj->number = number;
285
286 return (PyObject *) obj;
287}
288
289/* Implementation of RecordFunctionSegment.level [int]. */
290
291static PyObject *
292recpy_func_level (PyObject *self, void *closure)
293{
294 const recpy_element_object * const obj = (recpy_element_object *) self;
295
296 if (obj->method == RECORD_METHOD_BTRACE)
297 return recpy_bt_func_level (self, closure);
298
299 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
300}
301
302/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol]. */
303
304static PyObject *
305recpy_func_symbol (PyObject *self, void *closure)
306{
307 const recpy_element_object * const obj = (recpy_element_object *) self;
308
309 if (obj->method == RECORD_METHOD_BTRACE)
310 return recpy_bt_func_symbol (self, closure);
311
312 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
313}
314
315/* Implementation of RecordFunctionSegment.instructions [list]. */
316
317static PyObject *
318recpy_func_instructions (PyObject *self, void *closure)
319{
320 const recpy_element_object * const obj = (recpy_element_object *) self;
321
322 if (obj->method == RECORD_METHOD_BTRACE)
323 return recpy_bt_func_instructions (self, closure);
324
325 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
326}
327
328/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment]. */
329
330static PyObject *
331recpy_func_up (PyObject *self, void *closure)
332{
333 const recpy_element_object * const obj = (recpy_element_object *) self;
334
335 if (obj->method == RECORD_METHOD_BTRACE)
336 return recpy_bt_func_up (self, closure);
337
338 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
339}
340
341/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment]. */
342
343static PyObject *
344recpy_func_prev (PyObject *self, void *closure)
345{
346 const recpy_element_object * const obj = (recpy_element_object *) self;
347
348 if (obj->method == RECORD_METHOD_BTRACE)
349 return recpy_bt_func_prev (self, closure);
350
351 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
352}
353
354/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */
355
356static PyObject *
357recpy_func_next (PyObject *self, void *closure)
358{
359 const recpy_element_object * const obj = (recpy_element_object *) self;
360
361 if (obj->method == RECORD_METHOD_BTRACE)
362 return recpy_bt_func_next (self, closure);
363
364 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
365}
366
367/* Implementation of RecordInstruction.number [int] and
368 RecordFunctionSegment.number [int]. */
0ed5da75
TW
369
370static PyObject *
371recpy_element_number (PyObject *self, void* closure)
372{
373 const recpy_element_object * const obj = (recpy_element_object *) self;
374
375 return PyInt_FromSsize_t (obj->number);
376}
377
14f819c8
TW
378/* Implementation of RecordInstruction.__hash__ [int] and
379 RecordFunctionSegment.__hash__ [int]. */
380
0ed5da75
TW
381static Py_hash_t
382recpy_element_hash (PyObject *self)
383{
384 const recpy_element_object * const obj = (recpy_element_object *) self;
385
386 return obj->number;
387}
388
14f819c8
TW
389/* Implementation of operator == and != of RecordInstruction and
390 RecordFunctionSegment. */
0ed5da75
TW
391
392static PyObject *
393recpy_element_richcompare (PyObject *self, PyObject *other, int op)
394{
395 const recpy_element_object * const obj1 = (recpy_element_object *) self;
396 const recpy_element_object * const obj2 = (recpy_element_object *) other;
397
398 if (Py_TYPE (self) != Py_TYPE (other))
399 {
400 Py_INCREF (Py_NotImplemented);
401 return Py_NotImplemented;
402 }
403
404 switch (op)
405 {
406 case Py_EQ:
407 if (ptid_equal (obj1->ptid, obj2->ptid)
408 && obj1->method == obj2->method
409 && obj1->number == obj2->number)
410 Py_RETURN_TRUE;
411 else
412 Py_RETURN_FALSE;
413
414 case Py_NE:
415 if (!ptid_equal (obj1->ptid, obj2->ptid)
416 || obj1->method != obj2->method
417 || obj1->number != obj2->number)
418 Py_RETURN_TRUE;
419 else
420 Py_RETURN_FALSE;
421
422 default:
423 break;
424 }
425
426 Py_INCREF (Py_NotImplemented);
427 return Py_NotImplemented;
428}
429
913aeadd
TW
430/* Create a new gdb.RecordGap object. */
431
432PyObject *
433recpy_gap_new (int reason_code, const char *reason_string, Py_ssize_t number)
434{
435 recpy_gap_object * const obj = PyObject_New (recpy_gap_object,
436 &recpy_gap_type);
437
438 if (obj == NULL)
439 return NULL;
440
441 obj->reason_code = reason_code;
442 obj->reason_string = reason_string;
443 obj->number = number;
444
445 return (PyObject *) obj;
446}
447
448/* Implementation of RecordGap.number [int]. */
449
450static PyObject *
451recpy_gap_number (PyObject *self, void *closure)
452{
453 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
454
455 return PyInt_FromSsize_t (obj->number);
456}
457
458/* Implementation of RecordGap.error_code [int]. */
459
460static PyObject *
461recpy_gap_reason_code (PyObject *self, void *closure)
462{
463 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
464
465 return PyInt_FromLong (obj->reason_code);
466}
467
468/* Implementation of RecordGap.error_string [str]. */
469
470static PyObject *
471recpy_gap_reason_string (PyObject *self, void *closure)
472{
473 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
474
475 return PyString_FromString (obj->reason_string);
476}
477
4726b2d8
TW
478/* Record method list. */
479
480static PyMethodDef recpy_record_methods[] = {
481 { "goto", recpy_goto, METH_VARARGS,
482 "goto (instruction|function_call) -> None.\n\
483Rewind to given location."},
484 { NULL }
485};
486
487/* Record member list. */
488
0d1f4ceb 489static gdb_PyGetSetDef recpy_record_getset[] = {
4726b2d8
TW
490 { "method", recpy_method, NULL, "Current recording method.", NULL },
491 { "format", recpy_format, NULL, "Current recording format.", NULL },
492 { "replay_position", recpy_replay_position, NULL, "Current replay position.",
493 NULL },
494 { "instruction_history", recpy_instruction_history, NULL,
495 "List of instructions in current recording.", NULL },
496 { "function_call_history", recpy_function_call_history, NULL,
497 "List of function calls in current recording.", NULL },
498 { "begin", recpy_begin, NULL,
499 "First instruction in current recording.", NULL },
500 { "end", recpy_end, NULL,
501 "One past the last instruction in current recording. This is typically \
502the current instruction and is used for e.g. record.goto (record.end).", NULL },
503 { NULL }
504};
505
0ed5da75
TW
506/* RecordInstruction member list. */
507
508static gdb_PyGetSetDef recpy_insn_getset[] = {
509 { "number", recpy_element_number, NULL, "instruction number", NULL},
510 { "sal", recpy_insn_sal, NULL, "associated symbol and line", NULL},
511 { "pc", recpy_insn_pc, NULL, "instruction address", NULL},
512 { "data", recpy_insn_data, NULL, "raw instruction data", NULL},
513 { "decoded", recpy_insn_decoded, NULL, "decoded instruction", NULL},
514 { "size", recpy_insn_size, NULL, "instruction size in byte", NULL},
515 { "is_speculative", recpy_insn_is_speculative, NULL, "if the instruction was \
516 executed speculatively", NULL},
517 { NULL }
518};
519
14f819c8
TW
520/* RecordFunctionSegment member list. */
521
522static gdb_PyGetSetDef recpy_func_getset[] = {
523 { "number", recpy_element_number, NULL, "function segment number", NULL},
524 { "level", recpy_func_level, NULL, "call stack level", NULL},
525 { "symbol", recpy_func_symbol, NULL, "associated line and symbol", NULL},
526 { "instructions", recpy_func_instructions, NULL, "list of instructions in \
527this function segment", NULL},
528 { "up", recpy_func_up, NULL, "caller or returned-to function segment", NULL},
529 { "prev", recpy_func_prev, NULL, "previous segment of this function", NULL},
530 { "next", recpy_func_next, NULL, "next segment of this function", NULL},
531 { NULL }
532};
533
913aeadd
TW
534/* RecordGap member list. */
535
536static gdb_PyGetSetDef recpy_gap_getset[] = {
537 { "number", recpy_gap_number, NULL, "element number", NULL},
538 { "reason_code", recpy_gap_reason_code, NULL, "reason code", NULL},
539 { "reason_string", recpy_gap_reason_string, NULL, "reason string", NULL},
540 { NULL }
541};
542
4726b2d8
TW
543/* Sets up the record API in the gdb module. */
544
545int
546gdbpy_initialize_record (void)
547{
548 recpy_record_type.tp_new = PyType_GenericNew;
549 recpy_record_type.tp_flags = Py_TPFLAGS_DEFAULT;
550 recpy_record_type.tp_basicsize = sizeof (recpy_record_object);
551 recpy_record_type.tp_name = "gdb.Record";
552 recpy_record_type.tp_doc = "GDB record object";
553 recpy_record_type.tp_methods = recpy_record_methods;
554 recpy_record_type.tp_getset = recpy_record_getset;
555
0ed5da75
TW
556 recpy_insn_type.tp_new = PyType_GenericNew;
557 recpy_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
558 recpy_insn_type.tp_basicsize = sizeof (recpy_element_object);
559 recpy_insn_type.tp_name = "gdb.RecordInstruction";
560 recpy_insn_type.tp_doc = "GDB recorded instruction object";
561 recpy_insn_type.tp_getset = recpy_insn_getset;
562 recpy_insn_type.tp_richcompare = recpy_element_richcompare;
563 recpy_insn_type.tp_hash = recpy_element_hash;
564
14f819c8
TW
565 recpy_func_type.tp_new = PyType_GenericNew;
566 recpy_func_type.tp_flags = Py_TPFLAGS_DEFAULT;
567 recpy_func_type.tp_basicsize = sizeof (recpy_element_object);
568 recpy_func_type.tp_name = "gdb.RecordFunctionSegment";
569 recpy_func_type.tp_doc = "GDB record function segment object";
570 recpy_func_type.tp_getset = recpy_func_getset;
571 recpy_func_type.tp_richcompare = recpy_element_richcompare;
572 recpy_func_type.tp_hash = recpy_element_hash;
573
913aeadd
TW
574 recpy_gap_type.tp_new = PyType_GenericNew;
575 recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT;
576 recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object);
577 recpy_gap_type.tp_name = "gdb.RecordGap";
578 recpy_gap_type.tp_doc = "GDB recorded gap object";
579 recpy_gap_type.tp_getset = recpy_gap_getset;
580
581 if (PyType_Ready (&recpy_record_type) < 0
0ed5da75 582 || PyType_Ready (&recpy_insn_type) < 0
14f819c8 583 || PyType_Ready (&recpy_func_type) < 0
913aeadd
TW
584 || PyType_Ready (&recpy_gap_type) < 0)
585 return -1;
586 else
587 return 0;
4726b2d8
TW
588}
589
590/* Implementation of gdb.start_recording (method) -> gdb.Record. */
591
592PyObject *
593gdbpy_start_recording (PyObject *self, PyObject *args)
594{
595 const char *method = NULL;
596 const char *format = NULL;
597 PyObject *ret = NULL;
598
599 if (!PyArg_ParseTuple (args, "|ss", &method, &format))
600 return NULL;
601
602 TRY
603 {
604 record_start (method, format, 0);
605 ret = gdbpy_current_recording (self, args);
606 }
607 CATCH (except, RETURN_MASK_ALL)
608 {
609 gdbpy_convert_exception (except);
610 }
611 END_CATCH
612
613 return ret;
614}
615
616/* Implementation of gdb.current_recording (self) -> gdb.Record. */
617
618PyObject *
619gdbpy_current_recording (PyObject *self, PyObject *args)
620{
621 recpy_record_object *ret = NULL;
622
623 if (find_record_target () == NULL)
624 Py_RETURN_NONE;
625
626 ret = PyObject_New (recpy_record_object, &recpy_record_type);
627 ret->ptid = inferior_ptid;
628 ret->method = target_record_method (inferior_ptid);
629
630 return (PyObject *) ret;
631}
632
633/* Implementation of gdb.stop_recording (self) -> None. */
634
635PyObject *
636gdbpy_stop_recording (PyObject *self, PyObject *args)
637{
638 PyObject *ret = NULL;
639
640 TRY
641 {
642 record_stop (0);
643 ret = Py_None;
644 Py_INCREF (Py_None);
645 }
646 CATCH (except, RETURN_MASK_ALL)
647 {
648 gdbpy_convert_exception (except);
649 }
650 END_CATCH
651
652 return ret;
653}
This page took 0.082432 seconds and 4 git commands to generate.