Python: Move and rename gdb.BtraceInstruction
[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
913aeadd
TW
38/* Python RecordGap type. */
39
40PyTypeObject recpy_gap_type = {
41 PyVarObject_HEAD_INIT (NULL, 0)
42};
43
44/* Python RecordGap object. */
45typedef struct
46{
47 PyObject_HEAD
48
49 /* Reason code. */
50 int reason_code;
51
52 /* Reason message. */
53 const char *reason_string;
54
55 /* Element number. */
56 Py_ssize_t number;
57} recpy_gap_object;
58
4726b2d8
TW
59/* Implementation of record.method. */
60
61static PyObject *
62recpy_method (PyObject *self, void* closure)
63{
75c0bdf4
TW
64 const recpy_record_object * const obj = (recpy_record_object *) self;
65
66 if (obj->method == RECORD_METHOD_FULL)
67 return recpy_full_method (self, closure);
68
69 if (obj->method == RECORD_METHOD_BTRACE)
70 return recpy_bt_method (self, closure);
71
4726b2d8
TW
72 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
73}
74
75/* Implementation of record.format. */
76
77static PyObject *
78recpy_format (PyObject *self, void* closure)
79{
75c0bdf4
TW
80 const recpy_record_object * const obj = (recpy_record_object *) self;
81
82 if (obj->method == RECORD_METHOD_FULL)
83 return recpy_full_format (self, closure);
84
85 if (obj->method == RECORD_METHOD_BTRACE)
86 return recpy_bt_format (self, closure);
87
4726b2d8
TW
88 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
89}
90
91/* Implementation of record.goto (instruction) -> None. */
92
93static PyObject *
94recpy_goto (PyObject *self, PyObject *value)
95{
75c0bdf4
TW
96 const recpy_record_object * const obj = (recpy_record_object *) self;
97
98 if (obj->method == RECORD_METHOD_BTRACE)
99 return recpy_bt_goto (self, value);
100
4726b2d8
TW
101 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
102}
103
104/* Implementation of record.replay_position [instruction] */
105
106static PyObject *
107recpy_replay_position (PyObject *self, void *closure)
108{
75c0bdf4
TW
109 const recpy_record_object * const obj = (recpy_record_object *) self;
110
111 if (obj->method == RECORD_METHOD_BTRACE)
112 return recpy_bt_replay_position (self, closure);
113
4726b2d8
TW
114 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
115}
116
117/* Implementation of record.instruction_history [list]. */
118
119static PyObject *
120recpy_instruction_history (PyObject *self, void* closure)
121{
75c0bdf4
TW
122 const recpy_record_object * const obj = (recpy_record_object *) self;
123
124 if (obj->method == RECORD_METHOD_BTRACE)
125 return recpy_bt_instruction_history (self, closure);
126
4726b2d8
TW
127 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
128}
129
130/* Implementation of record.function_call_history [list]. */
131
132static PyObject *
133recpy_function_call_history (PyObject *self, void* closure)
134{
75c0bdf4
TW
135 const recpy_record_object * const obj = (recpy_record_object *) self;
136
137 if (obj->method == RECORD_METHOD_BTRACE)
138 return recpy_bt_function_call_history (self, closure);
139
4726b2d8
TW
140 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
141}
142
143/* Implementation of record.begin [instruction]. */
144
145static PyObject *
146recpy_begin (PyObject *self, void* closure)
147{
75c0bdf4
TW
148 const recpy_record_object * const obj = (recpy_record_object *) self;
149
150 if (obj->method == RECORD_METHOD_BTRACE)
151 return recpy_bt_begin (self, closure);
152
4726b2d8
TW
153 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
154}
155
156/* Implementation of record.end [instruction]. */
157
158static PyObject *
159recpy_end (PyObject *self, void* closure)
160{
75c0bdf4
TW
161 const recpy_record_object * const obj = (recpy_record_object *) self;
162
163 if (obj->method == RECORD_METHOD_BTRACE)
164 return recpy_bt_end (self, closure);
165
4726b2d8
TW
166 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
167}
168
0ed5da75
TW
169/* Create a new gdb.RecordInstruction object. */
170
171PyObject *
172recpy_insn_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
173{
174 recpy_element_object * const obj = PyObject_New (recpy_element_object,
175 &recpy_insn_type);
176
177 if (obj == NULL)
178 return NULL;
179
180 obj->ptid = ptid;
181 obj->method = method;
182 obj->number = number;
183
184 return (PyObject *) obj;
185}
186
187/* Implementation of RecordInstruction.sal [gdb.Symtab_and_line]. */
188
189static PyObject *
190recpy_insn_sal (PyObject *self, void *closure)
191{
192 const recpy_element_object * const obj = (recpy_element_object *) self;
193
194 if (obj->method == RECORD_METHOD_BTRACE)
195 return recpy_bt_insn_sal (self, closure);
196
197 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
198}
199
200/* Implementation of RecordInstruction.pc [int]. */
201
202static PyObject *
203recpy_insn_pc (PyObject *self, void *closure)
204{
205 const recpy_element_object * const obj = (recpy_element_object *) self;
206
207 if (obj->method == RECORD_METHOD_BTRACE)
208 return recpy_bt_insn_pc (self, closure);
209
210 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
211}
212
213/* Implementation of RecordInstruction.data [buffer]. */
214
215static PyObject *
216recpy_insn_data (PyObject *self, void *closure)
217{
218 const recpy_element_object * const obj = (recpy_element_object *) self;
219
220 if (obj->method == RECORD_METHOD_BTRACE)
221 return recpy_bt_insn_data (self, closure);
222
223 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
224}
225
226/* Implementation of RecordInstruction.decoded [str]. */
227
228static PyObject *
229recpy_insn_decoded (PyObject *self, void *closure)
230{
231 const recpy_element_object * const obj = (recpy_element_object *) self;
232
233 if (obj->method == RECORD_METHOD_BTRACE)
234 return recpy_bt_insn_decoded (self, closure);
235
236 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
237}
238
239/* Implementation of RecordInstruction.size [int]. */
240
241static PyObject *
242recpy_insn_size (PyObject *self, void *closure)
243{
244 const recpy_element_object * const obj = (recpy_element_object *) self;
245
246 if (obj->method == RECORD_METHOD_BTRACE)
247 return recpy_bt_insn_size (self, closure);
248
249 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
250}
251
252/* Implementation of RecordInstruction.is_speculative [bool]. */
253
254static PyObject *
255recpy_insn_is_speculative (PyObject *self, void *closure)
256{
257 const recpy_element_object * const obj = (recpy_element_object *) self;
258
259 if (obj->method == RECORD_METHOD_BTRACE)
260 return recpy_bt_insn_is_speculative (self, closure);
261
262 return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
263}
264
265/* Implementation of RecordInstruction.number [int]. */
266
267static PyObject *
268recpy_element_number (PyObject *self, void* closure)
269{
270 const recpy_element_object * const obj = (recpy_element_object *) self;
271
272 return PyInt_FromSsize_t (obj->number);
273}
274
275/* Implementation of RecordInstruction.__hash__ [int]. */
276static Py_hash_t
277recpy_element_hash (PyObject *self)
278{
279 const recpy_element_object * const obj = (recpy_element_object *) self;
280
281 return obj->number;
282}
283
284/* Implementation of operator == and != of RecordInstruction. */
285
286static PyObject *
287recpy_element_richcompare (PyObject *self, PyObject *other, int op)
288{
289 const recpy_element_object * const obj1 = (recpy_element_object *) self;
290 const recpy_element_object * const obj2 = (recpy_element_object *) other;
291
292 if (Py_TYPE (self) != Py_TYPE (other))
293 {
294 Py_INCREF (Py_NotImplemented);
295 return Py_NotImplemented;
296 }
297
298 switch (op)
299 {
300 case Py_EQ:
301 if (ptid_equal (obj1->ptid, obj2->ptid)
302 && obj1->method == obj2->method
303 && obj1->number == obj2->number)
304 Py_RETURN_TRUE;
305 else
306 Py_RETURN_FALSE;
307
308 case Py_NE:
309 if (!ptid_equal (obj1->ptid, obj2->ptid)
310 || obj1->method != obj2->method
311 || obj1->number != obj2->number)
312 Py_RETURN_TRUE;
313 else
314 Py_RETURN_FALSE;
315
316 default:
317 break;
318 }
319
320 Py_INCREF (Py_NotImplemented);
321 return Py_NotImplemented;
322}
323
913aeadd
TW
324/* Create a new gdb.RecordGap object. */
325
326PyObject *
327recpy_gap_new (int reason_code, const char *reason_string, Py_ssize_t number)
328{
329 recpy_gap_object * const obj = PyObject_New (recpy_gap_object,
330 &recpy_gap_type);
331
332 if (obj == NULL)
333 return NULL;
334
335 obj->reason_code = reason_code;
336 obj->reason_string = reason_string;
337 obj->number = number;
338
339 return (PyObject *) obj;
340}
341
342/* Implementation of RecordGap.number [int]. */
343
344static PyObject *
345recpy_gap_number (PyObject *self, void *closure)
346{
347 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
348
349 return PyInt_FromSsize_t (obj->number);
350}
351
352/* Implementation of RecordGap.error_code [int]. */
353
354static PyObject *
355recpy_gap_reason_code (PyObject *self, void *closure)
356{
357 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
358
359 return PyInt_FromLong (obj->reason_code);
360}
361
362/* Implementation of RecordGap.error_string [str]. */
363
364static PyObject *
365recpy_gap_reason_string (PyObject *self, void *closure)
366{
367 const recpy_gap_object * const obj = (const recpy_gap_object *) self;
368
369 return PyString_FromString (obj->reason_string);
370}
371
4726b2d8
TW
372/* Record method list. */
373
374static PyMethodDef recpy_record_methods[] = {
375 { "goto", recpy_goto, METH_VARARGS,
376 "goto (instruction|function_call) -> None.\n\
377Rewind to given location."},
378 { NULL }
379};
380
381/* Record member list. */
382
0d1f4ceb 383static gdb_PyGetSetDef recpy_record_getset[] = {
4726b2d8
TW
384 { "method", recpy_method, NULL, "Current recording method.", NULL },
385 { "format", recpy_format, NULL, "Current recording format.", NULL },
386 { "replay_position", recpy_replay_position, NULL, "Current replay position.",
387 NULL },
388 { "instruction_history", recpy_instruction_history, NULL,
389 "List of instructions in current recording.", NULL },
390 { "function_call_history", recpy_function_call_history, NULL,
391 "List of function calls in current recording.", NULL },
392 { "begin", recpy_begin, NULL,
393 "First instruction in current recording.", NULL },
394 { "end", recpy_end, NULL,
395 "One past the last instruction in current recording. This is typically \
396the current instruction and is used for e.g. record.goto (record.end).", NULL },
397 { NULL }
398};
399
0ed5da75
TW
400/* RecordInstruction member list. */
401
402static gdb_PyGetSetDef recpy_insn_getset[] = {
403 { "number", recpy_element_number, NULL, "instruction number", NULL},
404 { "sal", recpy_insn_sal, NULL, "associated symbol and line", NULL},
405 { "pc", recpy_insn_pc, NULL, "instruction address", NULL},
406 { "data", recpy_insn_data, NULL, "raw instruction data", NULL},
407 { "decoded", recpy_insn_decoded, NULL, "decoded instruction", NULL},
408 { "size", recpy_insn_size, NULL, "instruction size in byte", NULL},
409 { "is_speculative", recpy_insn_is_speculative, NULL, "if the instruction was \
410 executed speculatively", NULL},
411 { NULL }
412};
413
913aeadd
TW
414/* RecordGap member list. */
415
416static gdb_PyGetSetDef recpy_gap_getset[] = {
417 { "number", recpy_gap_number, NULL, "element number", NULL},
418 { "reason_code", recpy_gap_reason_code, NULL, "reason code", NULL},
419 { "reason_string", recpy_gap_reason_string, NULL, "reason string", NULL},
420 { NULL }
421};
422
4726b2d8
TW
423/* Sets up the record API in the gdb module. */
424
425int
426gdbpy_initialize_record (void)
427{
428 recpy_record_type.tp_new = PyType_GenericNew;
429 recpy_record_type.tp_flags = Py_TPFLAGS_DEFAULT;
430 recpy_record_type.tp_basicsize = sizeof (recpy_record_object);
431 recpy_record_type.tp_name = "gdb.Record";
432 recpy_record_type.tp_doc = "GDB record object";
433 recpy_record_type.tp_methods = recpy_record_methods;
434 recpy_record_type.tp_getset = recpy_record_getset;
435
0ed5da75
TW
436 recpy_insn_type.tp_new = PyType_GenericNew;
437 recpy_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
438 recpy_insn_type.tp_basicsize = sizeof (recpy_element_object);
439 recpy_insn_type.tp_name = "gdb.RecordInstruction";
440 recpy_insn_type.tp_doc = "GDB recorded instruction object";
441 recpy_insn_type.tp_getset = recpy_insn_getset;
442 recpy_insn_type.tp_richcompare = recpy_element_richcompare;
443 recpy_insn_type.tp_hash = recpy_element_hash;
444
913aeadd
TW
445 recpy_gap_type.tp_new = PyType_GenericNew;
446 recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT;
447 recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object);
448 recpy_gap_type.tp_name = "gdb.RecordGap";
449 recpy_gap_type.tp_doc = "GDB recorded gap object";
450 recpy_gap_type.tp_getset = recpy_gap_getset;
451
452 if (PyType_Ready (&recpy_record_type) < 0
0ed5da75 453 || PyType_Ready (&recpy_insn_type) < 0
913aeadd
TW
454 || PyType_Ready (&recpy_gap_type) < 0)
455 return -1;
456 else
457 return 0;
4726b2d8
TW
458}
459
460/* Implementation of gdb.start_recording (method) -> gdb.Record. */
461
462PyObject *
463gdbpy_start_recording (PyObject *self, PyObject *args)
464{
465 const char *method = NULL;
466 const char *format = NULL;
467 PyObject *ret = NULL;
468
469 if (!PyArg_ParseTuple (args, "|ss", &method, &format))
470 return NULL;
471
472 TRY
473 {
474 record_start (method, format, 0);
475 ret = gdbpy_current_recording (self, args);
476 }
477 CATCH (except, RETURN_MASK_ALL)
478 {
479 gdbpy_convert_exception (except);
480 }
481 END_CATCH
482
483 return ret;
484}
485
486/* Implementation of gdb.current_recording (self) -> gdb.Record. */
487
488PyObject *
489gdbpy_current_recording (PyObject *self, PyObject *args)
490{
491 recpy_record_object *ret = NULL;
492
493 if (find_record_target () == NULL)
494 Py_RETURN_NONE;
495
496 ret = PyObject_New (recpy_record_object, &recpy_record_type);
497 ret->ptid = inferior_ptid;
498 ret->method = target_record_method (inferior_ptid);
499
500 return (PyObject *) ret;
501}
502
503/* Implementation of gdb.stop_recording (self) -> None. */
504
505PyObject *
506gdbpy_stop_recording (PyObject *self, PyObject *args)
507{
508 PyObject *ret = NULL;
509
510 TRY
511 {
512 record_stop (0);
513 ret = Py_None;
514 Py_INCREF (Py_None);
515 }
516 CATCH (except, RETURN_MASK_ALL)
517 {
518 gdbpy_convert_exception (except);
519 }
520 END_CATCH
521
522 return ret;
523}
This page took 0.06301 seconds and 4 git commands to generate.