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