1 /* Python interface to inferiors.
3 Copyright (C) 2009-2023 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "auto-load.h"
23 #include "gdbthread.h"
26 #include "observable.h"
27 #include "python-internal.h"
28 #include "arch-utils.h"
30 #include "gdbsupport/gdb_signals.h"
32 #include "py-stopevent.h"
33 #include <unordered_map>
36 = std::unordered_map
<thread_info
*, gdbpy_ref
<thread_object
>>;
38 struct inferior_object
42 /* The inferior we represent. */
43 struct inferior
*inferior
;
45 /* thread_object instances under this inferior. This owns a
46 reference to each object it contains. */
47 thread_map_t
*threads
;
50 extern PyTypeObject inferior_object_type
51 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
53 /* Deleter to clean up when an inferior is removed. */
56 void operator() (inferior_object
*obj
)
58 if (!gdb_python_initialized
)
62 gdbpy_ref
<inferior_object
> inf_obj (obj
);
64 inf_obj
->inferior
= NULL
;
66 delete inf_obj
->threads
;
70 static const registry
<inferior
>::key
<inferior_object
, infpy_deleter
>
73 /* Require that INFERIOR be a valid inferior ID. */
74 #define INFPY_REQUIRE_VALID(Inferior) \
76 if (!Inferior->inferior) \
78 PyErr_SetString (PyExc_RuntimeError, \
79 _("Inferior no longer exists.")); \
85 python_on_normal_stop (struct bpstat
*bs
, int print_frame
)
87 enum gdb_signal stop_signal
;
89 if (!gdb_python_initialized
)
92 if (inferior_ptid
== null_ptid
)
95 stop_signal
= inferior_thread ()->stop_signal ();
99 if (emit_stop_event (bs
, stop_signal
) < 0)
100 gdbpy_print_stack ();
104 python_on_resume (ptid_t ptid
)
106 if (!gdb_python_initialized
)
109 gdbpy_enter
enter_py (target_gdbarch ());
111 if (emit_continue_event (ptid
) < 0)
112 gdbpy_print_stack ();
115 /* Callback, registered as an observer, that notifies Python listeners
116 when an inferior function call is about to be made. */
119 python_on_inferior_call_pre (ptid_t thread
, CORE_ADDR address
)
121 gdbpy_enter
enter_py (target_gdbarch ());
123 if (emit_inferior_call_event (INFERIOR_CALL_PRE
, thread
, address
) < 0)
124 gdbpy_print_stack ();
127 /* Callback, registered as an observer, that notifies Python listeners
128 when an inferior function call has completed. */
131 python_on_inferior_call_post (ptid_t thread
, CORE_ADDR address
)
133 gdbpy_enter
enter_py (target_gdbarch ());
135 if (emit_inferior_call_event (INFERIOR_CALL_POST
, thread
, address
) < 0)
136 gdbpy_print_stack ();
139 /* Callback, registered as an observer, that notifies Python listeners
140 when a part of memory has been modified by user action (eg via a
144 python_on_memory_change (struct inferior
*inferior
, CORE_ADDR addr
, ssize_t len
, const bfd_byte
*data
)
146 gdbpy_enter
enter_py (target_gdbarch ());
148 if (emit_memory_changed_event (addr
, len
) < 0)
149 gdbpy_print_stack ();
152 /* Callback, registered as an observer, that notifies Python listeners
153 when a register has been modified by user action (eg via a 'set'
157 python_on_register_change (frame_info_ptr frame
, int regnum
)
159 gdbpy_enter
enter_py (target_gdbarch ());
161 if (emit_register_changed_event (frame
, regnum
) < 0)
162 gdbpy_print_stack ();
166 python_inferior_exit (struct inferior
*inf
)
168 const LONGEST
*exit_code
= NULL
;
170 if (!gdb_python_initialized
)
173 gdbpy_enter
enter_py (target_gdbarch ());
175 if (inf
->has_exit_code
)
176 exit_code
= &inf
->exit_code
;
178 if (emit_exited_event (exit_code
, inf
) < 0)
179 gdbpy_print_stack ();
182 /* Callback used to notify Python listeners about new objfiles loaded in the
183 inferior. OBJFILE may be NULL which means that the objfile list has been
184 cleared (emptied). */
187 python_new_objfile (struct objfile
*objfile
)
189 if (!gdb_python_initialized
)
192 gdbpy_enter
enter_py (objfile
!= NULL
194 : target_gdbarch ());
198 if (emit_clear_objfiles_event () < 0)
199 gdbpy_print_stack ();
203 if (emit_new_objfile_event (objfile
) < 0)
204 gdbpy_print_stack ();
208 /* Emit a Python event when an objfile is about to be removed. */
211 python_free_objfile (struct objfile
*objfile
)
213 if (!gdb_python_initialized
)
216 gdbpy_enter
enter_py (objfile
->arch ());
218 if (emit_free_objfile_event (objfile
) < 0)
219 gdbpy_print_stack ();
222 /* Return a reference to the Python object of type Inferior
223 representing INFERIOR. If the object has already been created,
224 return it and increment the reference count, otherwise, create it.
225 Return NULL on failure. */
227 gdbpy_ref
<inferior_object
>
228 inferior_to_inferior_object (struct inferior
*inferior
)
230 inferior_object
*inf_obj
;
232 inf_obj
= infpy_inf_data_key
.get (inferior
);
235 inf_obj
= PyObject_New (inferior_object
, &inferior_object_type
);
239 inf_obj
->inferior
= inferior
;
240 inf_obj
->threads
= new thread_map_t ();
242 /* PyObject_New initializes the new object with a refcount of 1. This
243 counts for the reference we are keeping in the inferior data. */
244 infpy_inf_data_key
.set (inferior
, inf_obj
);
247 /* We are returning a new reference. */
248 gdb_assert (inf_obj
!= nullptr);
249 return gdbpy_ref
<inferior_object
>::new_reference (inf_obj
);
252 /* Called when a new inferior is created. Notifies any Python event
255 python_new_inferior (struct inferior
*inf
)
257 if (!gdb_python_initialized
)
260 gdbpy_enter enter_py
;
262 if (evregpy_no_listeners_p (gdb_py_events
.new_inferior
))
265 gdbpy_ref
<inferior_object
> inf_obj
= inferior_to_inferior_object (inf
);
268 gdbpy_print_stack ();
272 gdbpy_ref
<> event
= create_event_object (&new_inferior_event_object_type
);
274 || evpy_add_attribute (event
.get (), "inferior",
275 (PyObject
*) inf_obj
.get ()) < 0
276 || evpy_emit_event (event
.get (), gdb_py_events
.new_inferior
) < 0)
277 gdbpy_print_stack ();
280 /* Called when an inferior is removed. Notifies any Python event
283 python_inferior_deleted (struct inferior
*inf
)
285 if (!gdb_python_initialized
)
288 gdbpy_enter enter_py
;
290 if (evregpy_no_listeners_p (gdb_py_events
.inferior_deleted
))
293 gdbpy_ref
<inferior_object
> inf_obj
= inferior_to_inferior_object (inf
);
296 gdbpy_print_stack ();
300 gdbpy_ref
<> event
= create_event_object (&inferior_deleted_event_object_type
);
302 || evpy_add_attribute (event
.get (), "inferior",
303 (PyObject
*) inf_obj
.get ()) < 0
304 || evpy_emit_event (event
.get (), gdb_py_events
.inferior_deleted
) < 0)
305 gdbpy_print_stack ();
309 thread_to_thread_object (thread_info
*thr
)
311 gdbpy_ref
<inferior_object
> inf_obj
= inferior_to_inferior_object (thr
->inf
);
315 auto thread_it
= inf_obj
->threads
->find (thr
);
316 if (thread_it
!= inf_obj
->threads
->end ())
317 return gdbpy_ref
<>::new_reference
318 ((PyObject
*) (thread_it
->second
.get ()));
320 PyErr_SetString (PyExc_SystemError
,
321 _("could not find gdb thread object"));
326 add_thread_object (struct thread_info
*tp
)
328 inferior_object
*inf_obj
;
330 if (!gdb_python_initialized
)
333 gdbpy_enter enter_py
;
335 gdbpy_ref
<thread_object
> thread_obj
= create_thread_object (tp
);
336 if (thread_obj
== NULL
)
338 gdbpy_print_stack ();
342 inf_obj
= (inferior_object
*) thread_obj
->inf_obj
;
344 auto ins_result
= inf_obj
->threads
->emplace
345 (thread_map_t::value_type (tp
, std::move (thread_obj
)));
347 if (!ins_result
.second
)
350 if (evregpy_no_listeners_p (gdb_py_events
.new_thread
))
353 gdbpy_ref
<> event
= create_thread_event_object
354 (&new_thread_event_object_type
,
355 (PyObject
*) ins_result
.first
->second
.get ());
358 || evpy_emit_event (event
.get (), gdb_py_events
.new_thread
) < 0)
359 gdbpy_print_stack ();
363 delete_thread_object (struct thread_info
*tp
, int ignore
)
365 if (!gdb_python_initialized
)
368 gdbpy_enter enter_py
;
370 gdbpy_ref
<inferior_object
> inf_obj
= inferior_to_inferior_object (tp
->inf
);
374 auto it
= inf_obj
->threads
->find (tp
);
375 if (it
!= inf_obj
->threads
->end ())
377 /* Some python code can still hold a reference to the thread_object
378 instance. Make sure to remove the link to the associated
379 thread_info object as it will be freed soon. This makes the python
380 object invalid (i.e. gdb.InfThread.is_valid returns False). */
381 it
->second
->thread
= nullptr;
382 inf_obj
->threads
->erase (it
);
387 infpy_threads (PyObject
*self
, PyObject
*args
)
390 inferior_object
*inf_obj
= (inferior_object
*) self
;
393 INFPY_REQUIRE_VALID (inf_obj
);
397 update_thread_list ();
399 catch (const gdb_exception
&except
)
401 GDB_PY_HANDLE_EXCEPTION (except
);
404 tuple
= PyTuple_New (inf_obj
->threads
->size ());
408 for (const thread_map_t::value_type
&entry
: *inf_obj
->threads
)
410 PyObject
*thr
= (PyObject
*) entry
.second
.get ();
412 PyTuple_SET_ITEM (tuple
, i
, thr
);
420 infpy_get_num (PyObject
*self
, void *closure
)
422 inferior_object
*inf
= (inferior_object
*) self
;
424 INFPY_REQUIRE_VALID (inf
);
426 return gdb_py_object_from_longest (inf
->inferior
->num
).release ();
429 /* Return the gdb.TargetConnection object for this inferior, or None if a
430 connection does not exist. */
433 infpy_get_connection (PyObject
*self
, void *closure
)
435 inferior_object
*inf
= (inferior_object
*) self
;
437 INFPY_REQUIRE_VALID (inf
);
439 process_stratum_target
*target
= inf
->inferior
->process_target ();
440 return target_to_connection_object (target
).release ();
443 /* Return the connection number of the given inferior, or None if a
444 connection does not exist. */
447 infpy_get_connection_num (PyObject
*self
, void *closure
)
449 inferior_object
*inf
= (inferior_object
*) self
;
451 INFPY_REQUIRE_VALID (inf
);
453 process_stratum_target
*target
= inf
->inferior
->process_target ();
454 if (target
== nullptr)
457 return gdb_py_object_from_longest (target
->connection_number
).release ();
461 infpy_get_pid (PyObject
*self
, void *closure
)
463 inferior_object
*inf
= (inferior_object
*) self
;
465 INFPY_REQUIRE_VALID (inf
);
467 return gdb_py_object_from_longest (inf
->inferior
->pid
).release ();
471 infpy_get_was_attached (PyObject
*self
, void *closure
)
473 inferior_object
*inf
= (inferior_object
*) self
;
475 INFPY_REQUIRE_VALID (inf
);
476 if (inf
->inferior
->attach_flag
)
481 /* Getter of gdb.Inferior.progspace. */
484 infpy_get_progspace (PyObject
*self
, void *closure
)
486 inferior_object
*inf
= (inferior_object
*) self
;
488 INFPY_REQUIRE_VALID (inf
);
490 program_space
*pspace
= inf
->inferior
->pspace
;
491 gdb_assert (pspace
!= nullptr);
493 return pspace_to_pspace_object (pspace
).release ();
496 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
497 Returns a tuple of all inferiors. */
499 gdbpy_inferiors (PyObject
*unused
, PyObject
*unused2
)
501 gdbpy_ref
<> list (PyList_New (0));
505 for (inferior
*inf
: all_inferiors ())
507 gdbpy_ref
<inferior_object
> inferior
= inferior_to_inferior_object (inf
);
509 if (inferior
== NULL
)
512 if (PyList_Append (list
.get (), (PyObject
*) inferior
.get ()) != 0)
516 return PyList_AsTuple (list
.get ());
519 /* Membuf and memory manipulation. */
521 /* Implementation of Inferior.read_memory (address, length).
522 Returns a Python buffer object with LENGTH bytes of the inferior's
523 memory at ADDRESS. Both arguments are integers. Returns NULL on error,
524 with a python exception set. */
526 infpy_read_memory (PyObject
*self
, PyObject
*args
, PyObject
*kw
)
528 CORE_ADDR addr
, length
;
529 gdb::unique_xmalloc_ptr
<gdb_byte
> buffer
;
530 PyObject
*addr_obj
, *length_obj
;
531 static const char *keywords
[] = { "address", "length", NULL
};
533 if (!gdb_PyArg_ParseTupleAndKeywords (args
, kw
, "OO", keywords
,
534 &addr_obj
, &length_obj
))
537 if (get_addr_from_python (addr_obj
, &addr
) < 0
538 || get_addr_from_python (length_obj
, &length
) < 0)
543 buffer
.reset ((gdb_byte
*) xmalloc (length
));
545 read_memory (addr
, buffer
.get (), length
);
547 catch (const gdb_exception
&except
)
549 GDB_PY_HANDLE_EXCEPTION (except
);
553 return gdbpy_buffer_to_membuf (std::move (buffer
), addr
, length
);
556 /* Implementation of Inferior.write_memory (address, buffer [, length]).
557 Writes the contents of BUFFER (a Python object supporting the read
558 buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
559 bytes from BUFFER, or its entire contents if the argument is not
560 provided. The function returns nothing. Returns NULL on error, with
561 a python exception set. */
563 infpy_write_memory (PyObject
*self
, PyObject
*args
, PyObject
*kw
)
565 struct gdb_exception except
;
567 const gdb_byte
*buffer
;
568 CORE_ADDR addr
, length
;
569 PyObject
*addr_obj
, *length_obj
= NULL
;
570 static const char *keywords
[] = { "address", "buffer", "length", NULL
};
573 if (!gdb_PyArg_ParseTupleAndKeywords (args
, kw
, "Os*|O", keywords
,
574 &addr_obj
, &pybuf
, &length_obj
))
577 Py_buffer_up
buffer_up (&pybuf
);
578 buffer
= (const gdb_byte
*) pybuf
.buf
;
581 if (get_addr_from_python (addr_obj
, &addr
) < 0)
586 else if (get_addr_from_python (length_obj
, &length
) < 0)
591 write_memory_with_notification (addr
, buffer
, length
);
593 catch (gdb_exception
&ex
)
595 except
= std::move (ex
);
598 GDB_PY_HANDLE_EXCEPTION (except
);
604 gdb.search_memory (address, length, pattern). ADDRESS is the
605 address to start the search. LENGTH specifies the scope of the
606 search from ADDRESS. PATTERN is the pattern to search for (and
607 must be a Python object supporting the buffer protocol).
608 Returns a Python Long object holding the address where the pattern
609 was located, or if the pattern was not found, returns None. Returns NULL
610 on error, with a python exception set. */
612 infpy_search_memory (PyObject
*self
, PyObject
*args
, PyObject
*kw
)
614 struct gdb_exception except
;
615 CORE_ADDR start_addr
, length
;
616 static const char *keywords
[] = { "address", "length", "pattern", NULL
};
617 PyObject
*start_addr_obj
, *length_obj
;
618 Py_ssize_t pattern_size
;
619 const gdb_byte
*buffer
;
620 CORE_ADDR found_addr
;
624 if (!gdb_PyArg_ParseTupleAndKeywords (args
, kw
, "OOs*", keywords
,
625 &start_addr_obj
, &length_obj
,
629 Py_buffer_up
buffer_up (&pybuf
);
630 buffer
= (const gdb_byte
*) pybuf
.buf
;
631 pattern_size
= pybuf
.len
;
633 if (get_addr_from_python (start_addr_obj
, &start_addr
) < 0)
636 if (get_addr_from_python (length_obj
, &length
) < 0)
641 PyErr_SetString (PyExc_ValueError
,
642 _("Search range is empty."));
645 /* Watch for overflows. */
646 else if (length
> CORE_ADDR_MAX
647 || (start_addr
+ length
- 1) < start_addr
)
649 PyErr_SetString (PyExc_ValueError
,
650 _("The search range is too large."));
656 found
= target_search_memory (start_addr
, length
,
657 buffer
, pattern_size
,
660 catch (gdb_exception
&ex
)
662 except
= std::move (ex
);
665 GDB_PY_HANDLE_EXCEPTION (except
);
668 return gdb_py_object_from_ulongest (found_addr
).release ();
673 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
674 Returns True if this inferior object still exists in GDB. */
677 infpy_is_valid (PyObject
*self
, PyObject
*args
)
679 inferior_object
*inf
= (inferior_object
*) self
;
687 /* Implementation of gdb.Inferior.thread_from_handle (self, handle)
688 -> gdb.InferiorThread. */
691 infpy_thread_from_thread_handle (PyObject
*self
, PyObject
*args
, PyObject
*kw
)
693 PyObject
*handle_obj
;
694 inferior_object
*inf_obj
= (inferior_object
*) self
;
695 static const char *keywords
[] = { "handle", NULL
};
697 INFPY_REQUIRE_VALID (inf_obj
);
699 if (! gdb_PyArg_ParseTupleAndKeywords (args
, kw
, "O", keywords
, &handle_obj
))
702 const gdb_byte
*bytes
;
704 Py_buffer_up buffer_up
;
707 if (PyObject_CheckBuffer (handle_obj
)
708 && PyObject_GetBuffer (handle_obj
, &py_buf
, PyBUF_SIMPLE
) == 0)
710 buffer_up
.reset (&py_buf
);
711 bytes
= (const gdb_byte
*) py_buf
.buf
;
712 bytes_len
= py_buf
.len
;
714 else if (gdbpy_is_value_object (handle_obj
))
716 struct value
*val
= value_object_to_value (handle_obj
);
717 bytes
= value_contents_all (val
).data ();
718 bytes_len
= value_type (val
)->length ();
722 PyErr_SetString (PyExc_TypeError
,
723 _("Argument 'handle' must be a thread handle object."));
730 struct thread_info
*thread_info
;
732 thread_info
= find_thread_by_handle
733 (gdb::array_view
<const gdb_byte
> (bytes
, bytes_len
),
735 if (thread_info
!= NULL
)
736 return thread_to_thread_object (thread_info
).release ();
738 catch (const gdb_exception
&except
)
740 GDB_PY_HANDLE_EXCEPTION (except
);
746 /* Implementation of gdb.Inferior.architecture. */
749 infpy_architecture (PyObject
*self
, PyObject
*args
)
751 inferior_object
*inf
= (inferior_object
*) self
;
753 INFPY_REQUIRE_VALID (inf
);
755 return gdbarch_to_arch_object (inf
->inferior
->gdbarch
);
758 /* Implement repr() for gdb.Inferior. */
761 infpy_repr (PyObject
*obj
)
763 inferior_object
*self
= (inferior_object
*) obj
;
764 inferior
*inf
= self
->inferior
;
767 return PyUnicode_FromString ("<gdb.Inferior (invalid)>");
769 return PyUnicode_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
775 infpy_dealloc (PyObject
*obj
)
777 inferior_object
*inf_obj
= (inferior_object
*) obj
;
779 /* The inferior itself holds a reference to this Python object, which
780 will keep the reference count of this object above zero until GDB
781 deletes the inferior and py_free_inferior is called.
783 Once py_free_inferior has been called then the link between this
784 Python object and the inferior is set to nullptr, and then the
785 reference count on this Python object is decremented.
787 The result of all this is that the link between this Python object and
788 the inferior should always have been set to nullptr before this
789 function is called. */
790 gdb_assert (inf_obj
->inferior
== nullptr);
792 Py_TYPE (obj
)->tp_free (obj
);
795 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
796 Returns the current inferior object. */
799 gdbpy_selected_inferior (PyObject
*self
, PyObject
*args
)
802 inferior_to_inferior_object (current_inferior ()).release ());
806 gdbpy_initialize_inferior (void)
808 if (PyType_Ready (&inferior_object_type
) < 0)
811 if (gdb_pymodule_addobject (gdb_module
, "Inferior",
812 (PyObject
*) &inferior_object_type
) < 0)
815 gdb::observers::new_thread
.attach (add_thread_object
, "py-inferior");
816 gdb::observers::thread_exit
.attach (delete_thread_object
, "py-inferior");
817 gdb::observers::normal_stop
.attach (python_on_normal_stop
, "py-inferior");
818 gdb::observers::target_resumed
.attach (python_on_resume
, "py-inferior");
819 gdb::observers::inferior_call_pre
.attach (python_on_inferior_call_pre
,
821 gdb::observers::inferior_call_post
.attach (python_on_inferior_call_post
,
823 gdb::observers::memory_changed
.attach (python_on_memory_change
,
825 gdb::observers::register_changed
.attach (python_on_register_change
,
827 gdb::observers::inferior_exit
.attach (python_inferior_exit
, "py-inferior");
828 /* Need to run after auto-load's new_objfile observer, so that
829 auto-loaded pretty-printers are available. */
830 gdb::observers::new_objfile
.attach
831 (python_new_objfile
, "py-inferior",
832 { &auto_load_new_objfile_observer_token
});
833 gdb::observers::free_objfile
.attach (python_free_objfile
, "py-inferior");
834 gdb::observers::inferior_added
.attach (python_new_inferior
, "py-inferior");
835 gdb::observers::inferior_removed
.attach (python_inferior_deleted
,
841 static gdb_PyGetSetDef inferior_object_getset
[] =
843 { "num", infpy_get_num
, NULL
, "ID of inferior, as assigned by GDB.", NULL
},
844 { "connection", infpy_get_connection
, NULL
,
845 "The gdb.TargetConnection for this inferior.", NULL
},
846 { "connection_num", infpy_get_connection_num
, NULL
,
847 "ID of inferior's connection, as assigned by GDB.", NULL
},
848 { "pid", infpy_get_pid
, NULL
, "PID of inferior, as assigned by the OS.",
850 { "was_attached", infpy_get_was_attached
, NULL
,
851 "True if the inferior was created using 'attach'.", NULL
},
852 { "progspace", infpy_get_progspace
, NULL
, "Program space of this inferior" },
856 static PyMethodDef inferior_object_methods
[] =
858 { "is_valid", infpy_is_valid
, METH_NOARGS
,
859 "is_valid () -> Boolean.\n\
860 Return true if this inferior is valid, false if not." },
861 { "threads", infpy_threads
, METH_NOARGS
,
862 "Return all the threads of this inferior." },
863 { "read_memory", (PyCFunction
) infpy_read_memory
,
864 METH_VARARGS
| METH_KEYWORDS
,
865 "read_memory (address, length) -> buffer\n\
866 Return a buffer object for reading from the inferior's memory." },
867 { "write_memory", (PyCFunction
) infpy_write_memory
,
868 METH_VARARGS
| METH_KEYWORDS
,
869 "write_memory (address, buffer [, length])\n\
870 Write the given buffer object to the inferior's memory." },
871 { "search_memory", (PyCFunction
) infpy_search_memory
,
872 METH_VARARGS
| METH_KEYWORDS
,
873 "search_memory (address, length, pattern) -> long\n\
874 Return a long with the address of a match, or None." },
875 /* thread_from_thread_handle is deprecated. */
876 { "thread_from_thread_handle", (PyCFunction
) infpy_thread_from_thread_handle
,
877 METH_VARARGS
| METH_KEYWORDS
,
878 "thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
879 Return thread object corresponding to thread handle.\n\
880 This method is deprecated - use thread_from_handle instead." },
881 { "thread_from_handle", (PyCFunction
) infpy_thread_from_thread_handle
,
882 METH_VARARGS
| METH_KEYWORDS
,
883 "thread_from_handle (handle) -> gdb.InferiorThread.\n\
884 Return thread object corresponding to thread handle." },
885 { "architecture", (PyCFunction
) infpy_architecture
, METH_NOARGS
,
886 "architecture () -> gdb.Architecture\n\
887 Return architecture of this inferior." },
891 PyTypeObject inferior_object_type
=
893 PyVarObject_HEAD_INIT (NULL
, 0)
894 "gdb.Inferior", /* tp_name */
895 sizeof (inferior_object
), /* tp_basicsize */
897 infpy_dealloc
, /* tp_dealloc */
902 infpy_repr
, /* tp_repr */
903 0, /* tp_as_number */
904 0, /* tp_as_sequence */
905 0, /* tp_as_mapping */
911 0, /* tp_as_buffer */
912 Py_TPFLAGS_DEFAULT
, /* tp_flags */
913 "GDB inferior object", /* tp_doc */
916 0, /* tp_richcompare */
917 0, /* tp_weaklistoffset */
920 inferior_object_methods
, /* tp_methods */
922 inferior_object_getset
, /* tp_getset */
925 0, /* tp_descr_get */
926 0, /* tp_descr_set */
927 0, /* tp_dictoffset */