]>
Commit | Line | Data |
---|---|---|
1 | /* Python interface to architecture | |
2 | ||
3 | Copyright (C) 2013-2025 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 "gdbarch.h" | |
21 | #include "arch-utils.h" | |
22 | #include "disasm.h" | |
23 | #include "python-internal.h" | |
24 | ||
25 | struct arch_object { | |
26 | PyObject_HEAD | |
27 | struct gdbarch *gdbarch; | |
28 | }; | |
29 | ||
30 | static const registry<gdbarch>::key<PyObject, gdb::noop_deleter<PyObject>> | |
31 | arch_object_data; | |
32 | ||
33 | /* Require a valid Architecture. */ | |
34 | #define ARCHPY_REQUIRE_VALID(arch_obj, arch) \ | |
35 | do { \ | |
36 | arch = arch_object_to_gdbarch (arch_obj); \ | |
37 | if (arch == NULL) \ | |
38 | { \ | |
39 | PyErr_SetString (PyExc_RuntimeError, \ | |
40 | _("Architecture is invalid.")); \ | |
41 | return NULL; \ | |
42 | } \ | |
43 | } while (0) | |
44 | ||
45 | extern PyTypeObject arch_object_type | |
46 | CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("arch_object"); | |
47 | ||
48 | /* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch | |
49 | post init registration mechanism (gdbarch_data_register_post_init). */ | |
50 | ||
51 | static PyObject * | |
52 | arch_object_data_init (struct gdbarch *gdbarch) | |
53 | { | |
54 | arch_object *arch_obj = PyObject_New (arch_object, &arch_object_type); | |
55 | ||
56 | if (arch_obj == NULL) | |
57 | return NULL; | |
58 | ||
59 | arch_obj->gdbarch = gdbarch; | |
60 | ||
61 | return (PyObject *) arch_obj; | |
62 | } | |
63 | ||
64 | /* Returns the struct gdbarch value corresponding to the given Python | |
65 | architecture object OBJ, which must be a gdb.Architecture object. */ | |
66 | ||
67 | struct gdbarch * | |
68 | arch_object_to_gdbarch (PyObject *obj) | |
69 | { | |
70 | gdb_assert (gdbpy_is_architecture (obj)); | |
71 | ||
72 | arch_object *py_arch = (arch_object *) obj; | |
73 | return py_arch->gdbarch; | |
74 | } | |
75 | ||
76 | /* See python-internal.h. */ | |
77 | ||
78 | bool | |
79 | gdbpy_is_architecture (PyObject *obj) | |
80 | { | |
81 | return PyObject_TypeCheck (obj, &arch_object_type); | |
82 | } | |
83 | ||
84 | /* Returns the Python architecture object corresponding to GDBARCH. | |
85 | Returns a new reference to the arch_object associated as data with | |
86 | GDBARCH. */ | |
87 | ||
88 | PyObject * | |
89 | gdbarch_to_arch_object (struct gdbarch *gdbarch) | |
90 | { | |
91 | PyObject *new_ref = arch_object_data.get (gdbarch); | |
92 | if (new_ref == nullptr) | |
93 | { | |
94 | new_ref = arch_object_data_init (gdbarch); | |
95 | arch_object_data.set (gdbarch, new_ref); | |
96 | } | |
97 | ||
98 | /* new_ref could be NULL if creation failed. */ | |
99 | Py_XINCREF (new_ref); | |
100 | ||
101 | return new_ref; | |
102 | } | |
103 | ||
104 | /* Implementation of gdb.Architecture.name (self) -> String. | |
105 | Returns the name of the architecture as a string value. */ | |
106 | ||
107 | static PyObject * | |
108 | archpy_name (PyObject *self, PyObject *args) | |
109 | { | |
110 | struct gdbarch *gdbarch = NULL; | |
111 | const char *name; | |
112 | ||
113 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
114 | ||
115 | name = (gdbarch_bfd_arch_info (gdbarch))->printable_name; | |
116 | return PyUnicode_FromString (name); | |
117 | } | |
118 | ||
119 | /* Implementation of | |
120 | gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List. | |
121 | Returns a list of instructions in a memory address range. Each instruction | |
122 | in the list is a Python dict object. | |
123 | */ | |
124 | ||
125 | static PyObject * | |
126 | archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw) | |
127 | { | |
128 | static const char *keywords[] = { "start_pc", "end_pc", "count", NULL }; | |
129 | CORE_ADDR start = 0, end = 0; | |
130 | CORE_ADDR pc; | |
131 | long count = 0, i; | |
132 | PyObject *start_obj = nullptr, *end_obj = nullptr, *count_obj = nullptr; | |
133 | struct gdbarch *gdbarch = NULL; | |
134 | ||
135 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
136 | ||
137 | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O|OO", | |
138 | keywords, &start_obj, &end_obj, | |
139 | &count_obj)) | |
140 | return NULL; | |
141 | ||
142 | if (get_addr_from_python (start_obj, &start) < 0) | |
143 | return nullptr; | |
144 | ||
145 | if (end_obj != nullptr) | |
146 | { | |
147 | if (get_addr_from_python (end_obj, &end) < 0) | |
148 | return nullptr; | |
149 | ||
150 | if (end < start) | |
151 | { | |
152 | PyErr_SetString (PyExc_ValueError, | |
153 | _("Argument 'end_pc' should be greater than or " | |
154 | "equal to the argument 'start_pc'.")); | |
155 | ||
156 | return NULL; | |
157 | } | |
158 | } | |
159 | if (count_obj) | |
160 | { | |
161 | count = PyLong_AsLong (count_obj); | |
162 | if (PyErr_Occurred () || count < 0) | |
163 | { | |
164 | PyErr_SetString (PyExc_TypeError, | |
165 | _("Argument 'count' should be an non-negative " | |
166 | "integer.")); | |
167 | ||
168 | return NULL; | |
169 | } | |
170 | } | |
171 | ||
172 | gdbpy_ref<> result_list (PyList_New (0)); | |
173 | if (result_list == NULL) | |
174 | return NULL; | |
175 | ||
176 | for (pc = start, i = 0; | |
177 | /* All args are specified. */ | |
178 | (end_obj && count_obj && pc <= end && i < count) | |
179 | /* end_pc is specified, but no count. */ | |
180 | || (end_obj && count_obj == NULL && pc <= end) | |
181 | /* end_pc is not specified, but a count is. */ | |
182 | || (end_obj == NULL && count_obj && i < count) | |
183 | /* Both end_pc and count are not specified. */ | |
184 | || (end_obj == NULL && count_obj == NULL && pc == start);) | |
185 | { | |
186 | int insn_len = 0; | |
187 | gdbpy_ref<> insn_dict (PyDict_New ()); | |
188 | ||
189 | if (insn_dict == NULL) | |
190 | return NULL; | |
191 | if (PyList_Append (result_list.get (), insn_dict.get ())) | |
192 | return NULL; /* PyList_Append Sets the exception. */ | |
193 | ||
194 | string_file stb; | |
195 | ||
196 | try | |
197 | { | |
198 | insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL); | |
199 | } | |
200 | catch (const gdb_exception &except) | |
201 | { | |
202 | return gdbpy_handle_gdb_exception (nullptr, except); | |
203 | } | |
204 | ||
205 | gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc); | |
206 | if (pc_obj == nullptr) | |
207 | return nullptr; | |
208 | ||
209 | gdbpy_ref<> asm_obj | |
210 | (PyUnicode_FromString (!stb.empty () ? stb.c_str () : "<unknown>")); | |
211 | if (asm_obj == nullptr) | |
212 | return nullptr; | |
213 | ||
214 | gdbpy_ref<> len_obj = gdb_py_object_from_longest (insn_len); | |
215 | if (len_obj == nullptr) | |
216 | return nullptr; | |
217 | ||
218 | if (PyDict_SetItemString (insn_dict.get (), "addr", pc_obj.get ()) | |
219 | || PyDict_SetItemString (insn_dict.get (), "asm", asm_obj.get ()) | |
220 | || PyDict_SetItemString (insn_dict.get (), "length", len_obj.get ())) | |
221 | return NULL; | |
222 | ||
223 | pc += insn_len; | |
224 | i++; | |
225 | } | |
226 | ||
227 | return result_list.release (); | |
228 | } | |
229 | ||
230 | /* Implementation of gdb.Architecture.registers (self, reggroup) -> Iterator. | |
231 | Returns an iterator over register descriptors for registers in GROUP | |
232 | within the architecture SELF. */ | |
233 | ||
234 | static PyObject * | |
235 | archpy_registers (PyObject *self, PyObject *args, PyObject *kw) | |
236 | { | |
237 | static const char *keywords[] = { "reggroup", NULL }; | |
238 | struct gdbarch *gdbarch = NULL; | |
239 | const char *group_name = NULL; | |
240 | ||
241 | /* Parse method arguments. */ | |
242 | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|s", keywords, | |
243 | &group_name)) | |
244 | return NULL; | |
245 | ||
246 | /* Extract the gdbarch from the self object. */ | |
247 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
248 | ||
249 | return gdbpy_new_register_descriptor_iterator (gdbarch, group_name); | |
250 | } | |
251 | ||
252 | /* Implementation of gdb.Architecture.register_groups (self) -> Iterator. | |
253 | Returns an iterator that will give up all valid register groups in the | |
254 | architecture SELF. */ | |
255 | ||
256 | static PyObject * | |
257 | archpy_register_groups (PyObject *self, PyObject *args) | |
258 | { | |
259 | struct gdbarch *gdbarch = NULL; | |
260 | ||
261 | /* Extract the gdbarch from the self object. */ | |
262 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
263 | return gdbpy_new_reggroup_iterator (gdbarch); | |
264 | } | |
265 | ||
266 | /* Implementation of gdb.integer_type. */ | |
267 | static PyObject * | |
268 | archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) | |
269 | { | |
270 | static const char *keywords[] = { "size", "signed", NULL }; | |
271 | int size; | |
272 | PyObject *is_signed_obj = Py_True; | |
273 | ||
274 | if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "i|O!", keywords, | |
275 | &size, | |
276 | &PyBool_Type, &is_signed_obj)) | |
277 | return nullptr; | |
278 | ||
279 | /* Assume signed by default. */ | |
280 | gdb_assert (PyBool_Check (is_signed_obj)); | |
281 | bool is_signed = is_signed_obj == Py_True; | |
282 | ||
283 | struct gdbarch *gdbarch; | |
284 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
285 | ||
286 | const struct builtin_type *builtins = builtin_type (gdbarch); | |
287 | struct type *type = nullptr; | |
288 | switch (size) | |
289 | { | |
290 | case 0: | |
291 | type = builtins->builtin_int0; | |
292 | break; | |
293 | case 8: | |
294 | type = is_signed ? builtins->builtin_int8 : builtins->builtin_uint8; | |
295 | break; | |
296 | case 16: | |
297 | type = is_signed ? builtins->builtin_int16 : builtins->builtin_uint16; | |
298 | break; | |
299 | case 24: | |
300 | type = is_signed ? builtins->builtin_int24 : builtins->builtin_uint24; | |
301 | break; | |
302 | case 32: | |
303 | type = is_signed ? builtins->builtin_int32 : builtins->builtin_uint32; | |
304 | break; | |
305 | case 64: | |
306 | type = is_signed ? builtins->builtin_int64 : builtins->builtin_uint64; | |
307 | break; | |
308 | case 128: | |
309 | type = is_signed ? builtins->builtin_int128 : builtins->builtin_uint128; | |
310 | break; | |
311 | ||
312 | default: | |
313 | PyErr_SetString (PyExc_ValueError, | |
314 | _("no integer type of that size is available")); | |
315 | return nullptr; | |
316 | } | |
317 | ||
318 | return type_to_type_object (type); | |
319 | } | |
320 | ||
321 | /* Implementation of gdb.void_type. */ | |
322 | static PyObject * | |
323 | archpy_void_type (PyObject *self, PyObject *args) | |
324 | { | |
325 | struct gdbarch *gdbarch; | |
326 | ARCHPY_REQUIRE_VALID (self, gdbarch); | |
327 | ||
328 | return type_to_type_object (builtin_type (gdbarch)->builtin_void); | |
329 | } | |
330 | ||
331 | /* __repr__ implementation for gdb.Architecture. */ | |
332 | ||
333 | static PyObject * | |
334 | archpy_repr (PyObject *self) | |
335 | { | |
336 | const auto gdbarch = arch_object_to_gdbarch (self); | |
337 | if (gdbarch == nullptr) | |
338 | return gdb_py_invalid_object_repr (self); | |
339 | ||
340 | auto arch_info = gdbarch_bfd_arch_info (gdbarch); | |
341 | return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>", | |
342 | Py_TYPE (self)->tp_name, arch_info->arch_name, | |
343 | arch_info->printable_name); | |
344 | } | |
345 | ||
346 | /* Implementation of gdb.architecture_names(). Return a list of all the | |
347 | BFD architecture names that GDB understands. */ | |
348 | ||
349 | PyObject * | |
350 | gdbpy_all_architecture_names (PyObject *self, PyObject *args) | |
351 | { | |
352 | gdbpy_ref<> list (PyList_New (0)); | |
353 | if (list == nullptr) | |
354 | return nullptr; | |
355 | ||
356 | std::vector<const char *> name_list = gdbarch_printable_names (); | |
357 | for (const char *name : name_list) | |
358 | { | |
359 | gdbpy_ref <> py_name (PyUnicode_FromString (name)); | |
360 | if (py_name == nullptr) | |
361 | return nullptr; | |
362 | if (PyList_Append (list.get (), py_name.get ()) < 0) | |
363 | return nullptr; | |
364 | } | |
365 | ||
366 | return list.release (); | |
367 | } | |
368 | ||
369 | /* Initializes the Architecture class in the gdb module. */ | |
370 | ||
371 | static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION | |
372 | gdbpy_initialize_arch (void) | |
373 | { | |
374 | arch_object_type.tp_new = PyType_GenericNew; | |
375 | return gdbpy_type_ready (&arch_object_type); | |
376 | } | |
377 | ||
378 | GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch); | |
379 | ||
380 | \f | |
381 | ||
382 | static PyMethodDef arch_object_methods [] = { | |
383 | { "name", archpy_name, METH_NOARGS, | |
384 | "name () -> String.\n\ | |
385 | Return the name of the architecture as a string value." }, | |
386 | { "disassemble", (PyCFunction) archpy_disassemble, | |
387 | METH_VARARGS | METH_KEYWORDS, | |
388 | "disassemble (start_pc [, end_pc [, count]]) -> List.\n\ | |
389 | Return a list of at most COUNT disassembled instructions from START_PC to\n\ | |
390 | END_PC." }, | |
391 | { "integer_type", (PyCFunction) archpy_integer_type, | |
392 | METH_VARARGS | METH_KEYWORDS, | |
393 | "integer_type (size [, signed]) -> type\n\ | |
394 | Return an integer Type corresponding to the given bitsize and signed-ness.\n\ | |
395 | If not specified, the type defaults to signed." }, | |
396 | { "void_type", (PyCFunction) archpy_void_type, | |
397 | METH_NOARGS, | |
398 | "void_type () -> type\n\ | |
399 | Return a void Type." }, | |
400 | { "registers", (PyCFunction) archpy_registers, | |
401 | METH_VARARGS | METH_KEYWORDS, | |
402 | "registers ([ group-name ]) -> Iterator.\n\ | |
403 | Return an iterator of register descriptors for the registers in register\n\ | |
404 | group GROUP-NAME." }, | |
405 | { "register_groups", archpy_register_groups, | |
406 | METH_NOARGS, | |
407 | "register_groups () -> Iterator.\n\ | |
408 | Return an iterator over all of the register groups in this architecture." }, | |
409 | {NULL} /* Sentinel */ | |
410 | }; | |
411 | ||
412 | PyTypeObject arch_object_type = { | |
413 | PyVarObject_HEAD_INIT (NULL, 0) | |
414 | "gdb.Architecture", /* tp_name */ | |
415 | sizeof (arch_object), /* tp_basicsize */ | |
416 | 0, /* tp_itemsize */ | |
417 | 0, /* tp_dealloc */ | |
418 | 0, /* tp_print */ | |
419 | 0, /* tp_getattr */ | |
420 | 0, /* tp_setattr */ | |
421 | 0, /* tp_compare */ | |
422 | archpy_repr, /* tp_repr */ | |
423 | 0, /* tp_as_number */ | |
424 | 0, /* tp_as_sequence */ | |
425 | 0, /* tp_as_mapping */ | |
426 | 0, /* tp_hash */ | |
427 | 0, /* tp_call */ | |
428 | 0, /* tp_str */ | |
429 | 0, /* tp_getattro */ | |
430 | 0, /* tp_setattro */ | |
431 | 0, /* tp_as_buffer */ | |
432 | Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
433 | "GDB architecture object", /* tp_doc */ | |
434 | 0, /* tp_traverse */ | |
435 | 0, /* tp_clear */ | |
436 | 0, /* tp_richcompare */ | |
437 | 0, /* tp_weaklistoffset */ | |
438 | 0, /* tp_iter */ | |
439 | 0, /* tp_iternext */ | |
440 | arch_object_methods, /* tp_methods */ | |
441 | 0, /* tp_members */ | |
442 | 0, /* tp_getset */ | |
443 | 0, /* tp_base */ | |
444 | 0, /* tp_dict */ | |
445 | 0, /* tp_descr_get */ | |
446 | 0, /* tp_descr_set */ | |
447 | 0, /* tp_dictoffset */ | |
448 | 0, /* tp_init */ | |
449 | 0, /* tp_alloc */ | |
450 | }; |