Commit | Line | Data |
---|---|---|
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 | ||
28 | static PyTypeObject recpy_record_type = { | |
29 | PyVarObject_HEAD_INIT (NULL, 0) | |
30 | }; | |
31 | ||
4726b2d8 TW |
32 | /* Implementation of record.method. */ |
33 | ||
34 | static PyObject * | |
35 | recpy_method (PyObject *self, void* closure) | |
36 | { | |
75c0bdf4 TW |
37 | const recpy_record_object * const obj = (recpy_record_object *) self; |
38 | ||
39 | if (obj->method == RECORD_METHOD_FULL) | |
40 | return recpy_full_method (self, closure); | |
41 | ||
42 | if (obj->method == RECORD_METHOD_BTRACE) | |
43 | return recpy_bt_method (self, closure); | |
44 | ||
4726b2d8 TW |
45 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
46 | } | |
47 | ||
48 | /* Implementation of record.format. */ | |
49 | ||
50 | static PyObject * | |
51 | recpy_format (PyObject *self, void* closure) | |
52 | { | |
75c0bdf4 TW |
53 | const recpy_record_object * const obj = (recpy_record_object *) self; |
54 | ||
55 | if (obj->method == RECORD_METHOD_FULL) | |
56 | return recpy_full_format (self, closure); | |
57 | ||
58 | if (obj->method == RECORD_METHOD_BTRACE) | |
59 | return recpy_bt_format (self, closure); | |
60 | ||
4726b2d8 TW |
61 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
62 | } | |
63 | ||
64 | /* Implementation of record.goto (instruction) -> None. */ | |
65 | ||
66 | static PyObject * | |
67 | recpy_goto (PyObject *self, PyObject *value) | |
68 | { | |
75c0bdf4 TW |
69 | const recpy_record_object * const obj = (recpy_record_object *) self; |
70 | ||
71 | if (obj->method == RECORD_METHOD_BTRACE) | |
72 | return recpy_bt_goto (self, value); | |
73 | ||
4726b2d8 TW |
74 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
75 | } | |
76 | ||
77 | /* Implementation of record.replay_position [instruction] */ | |
78 | ||
79 | static PyObject * | |
80 | recpy_replay_position (PyObject *self, void *closure) | |
81 | { | |
75c0bdf4 TW |
82 | const recpy_record_object * const obj = (recpy_record_object *) self; |
83 | ||
84 | if (obj->method == RECORD_METHOD_BTRACE) | |
85 | return recpy_bt_replay_position (self, closure); | |
86 | ||
4726b2d8 TW |
87 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
88 | } | |
89 | ||
90 | /* Implementation of record.instruction_history [list]. */ | |
91 | ||
92 | static PyObject * | |
93 | recpy_instruction_history (PyObject *self, void* closure) | |
94 | { | |
75c0bdf4 TW |
95 | const recpy_record_object * const obj = (recpy_record_object *) self; |
96 | ||
97 | if (obj->method == RECORD_METHOD_BTRACE) | |
98 | return recpy_bt_instruction_history (self, closure); | |
99 | ||
4726b2d8 TW |
100 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
101 | } | |
102 | ||
103 | /* Implementation of record.function_call_history [list]. */ | |
104 | ||
105 | static PyObject * | |
106 | recpy_function_call_history (PyObject *self, void* closure) | |
107 | { | |
75c0bdf4 TW |
108 | const recpy_record_object * const obj = (recpy_record_object *) self; |
109 | ||
110 | if (obj->method == RECORD_METHOD_BTRACE) | |
111 | return recpy_bt_function_call_history (self, closure); | |
112 | ||
4726b2d8 TW |
113 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
114 | } | |
115 | ||
116 | /* Implementation of record.begin [instruction]. */ | |
117 | ||
118 | static PyObject * | |
119 | recpy_begin (PyObject *self, void* closure) | |
120 | { | |
75c0bdf4 TW |
121 | const recpy_record_object * const obj = (recpy_record_object *) self; |
122 | ||
123 | if (obj->method == RECORD_METHOD_BTRACE) | |
124 | return recpy_bt_begin (self, closure); | |
125 | ||
4726b2d8 TW |
126 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
127 | } | |
128 | ||
129 | /* Implementation of record.end [instruction]. */ | |
130 | ||
131 | static PyObject * | |
132 | recpy_end (PyObject *self, void* closure) | |
133 | { | |
75c0bdf4 TW |
134 | const recpy_record_object * const obj = (recpy_record_object *) self; |
135 | ||
136 | if (obj->method == RECORD_METHOD_BTRACE) | |
137 | return recpy_bt_end (self, closure); | |
138 | ||
4726b2d8 TW |
139 | return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); |
140 | } | |
141 | ||
142 | /* Record method list. */ | |
143 | ||
144 | static PyMethodDef recpy_record_methods[] = { | |
145 | { "goto", recpy_goto, METH_VARARGS, | |
146 | "goto (instruction|function_call) -> None.\n\ | |
147 | Rewind to given location."}, | |
148 | { NULL } | |
149 | }; | |
150 | ||
151 | /* Record member list. */ | |
152 | ||
0d1f4ceb | 153 | static gdb_PyGetSetDef recpy_record_getset[] = { |
4726b2d8 TW |
154 | { "method", recpy_method, NULL, "Current recording method.", NULL }, |
155 | { "format", recpy_format, NULL, "Current recording format.", NULL }, | |
156 | { "replay_position", recpy_replay_position, NULL, "Current replay position.", | |
157 | NULL }, | |
158 | { "instruction_history", recpy_instruction_history, NULL, | |
159 | "List of instructions in current recording.", NULL }, | |
160 | { "function_call_history", recpy_function_call_history, NULL, | |
161 | "List of function calls in current recording.", NULL }, | |
162 | { "begin", recpy_begin, NULL, | |
163 | "First instruction in current recording.", NULL }, | |
164 | { "end", recpy_end, NULL, | |
165 | "One past the last instruction in current recording. This is typically \ | |
166 | the current instruction and is used for e.g. record.goto (record.end).", NULL }, | |
167 | { NULL } | |
168 | }; | |
169 | ||
170 | /* Sets up the record API in the gdb module. */ | |
171 | ||
172 | int | |
173 | gdbpy_initialize_record (void) | |
174 | { | |
175 | recpy_record_type.tp_new = PyType_GenericNew; | |
176 | recpy_record_type.tp_flags = Py_TPFLAGS_DEFAULT; | |
177 | recpy_record_type.tp_basicsize = sizeof (recpy_record_object); | |
178 | recpy_record_type.tp_name = "gdb.Record"; | |
179 | recpy_record_type.tp_doc = "GDB record object"; | |
180 | recpy_record_type.tp_methods = recpy_record_methods; | |
181 | recpy_record_type.tp_getset = recpy_record_getset; | |
182 | ||
183 | return PyType_Ready (&recpy_record_type); | |
184 | } | |
185 | ||
186 | /* Implementation of gdb.start_recording (method) -> gdb.Record. */ | |
187 | ||
188 | PyObject * | |
189 | gdbpy_start_recording (PyObject *self, PyObject *args) | |
190 | { | |
191 | const char *method = NULL; | |
192 | const char *format = NULL; | |
193 | PyObject *ret = NULL; | |
194 | ||
195 | if (!PyArg_ParseTuple (args, "|ss", &method, &format)) | |
196 | return NULL; | |
197 | ||
198 | TRY | |
199 | { | |
200 | record_start (method, format, 0); | |
201 | ret = gdbpy_current_recording (self, args); | |
202 | } | |
203 | CATCH (except, RETURN_MASK_ALL) | |
204 | { | |
205 | gdbpy_convert_exception (except); | |
206 | } | |
207 | END_CATCH | |
208 | ||
209 | return ret; | |
210 | } | |
211 | ||
212 | /* Implementation of gdb.current_recording (self) -> gdb.Record. */ | |
213 | ||
214 | PyObject * | |
215 | gdbpy_current_recording (PyObject *self, PyObject *args) | |
216 | { | |
217 | recpy_record_object *ret = NULL; | |
218 | ||
219 | if (find_record_target () == NULL) | |
220 | Py_RETURN_NONE; | |
221 | ||
222 | ret = PyObject_New (recpy_record_object, &recpy_record_type); | |
223 | ret->ptid = inferior_ptid; | |
224 | ret->method = target_record_method (inferior_ptid); | |
225 | ||
226 | return (PyObject *) ret; | |
227 | } | |
228 | ||
229 | /* Implementation of gdb.stop_recording (self) -> None. */ | |
230 | ||
231 | PyObject * | |
232 | gdbpy_stop_recording (PyObject *self, PyObject *args) | |
233 | { | |
234 | PyObject *ret = NULL; | |
235 | ||
236 | TRY | |
237 | { | |
238 | record_stop (0); | |
239 | ret = Py_None; | |
240 | Py_INCREF (Py_None); | |
241 | } | |
242 | CATCH (except, RETURN_MASK_ALL) | |
243 | { | |
244 | gdbpy_convert_exception (except); | |
245 | } | |
246 | END_CATCH | |
247 | ||
248 | return ret; | |
249 | } |