GDB (xrefs)
py-infthread.c
Go to the documentation of this file.
1 /* Python interface to inferior threads.
2 
3  Copyright (C) 2009-2018 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"
21 #include "gdbthread.h"
22 #include "inferior.h"
23 #include "python-internal.h"
24 
25 extern PyTypeObject thread_object_type
26  CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");
27 
28 /* Require that INFERIOR be a valid inferior ID. */
29 #define THPY_REQUIRE_VALID(Thread) \
30  do { \
31  if (!Thread->thread) \
32  { \
33  PyErr_SetString (PyExc_RuntimeError, \
34  _("Thread no longer exists.")); \
35  return NULL; \
36  } \
37  } while (0)
38 
41 {
43 
44  thread_obj = PyObject_New (thread_object, &thread_object_type);
45  if (!thread_obj)
46  return NULL;
47 
48  thread_obj->thread = tp;
50 
51  return thread_obj;
52 }
53 
54 static void
55 thpy_dealloc (PyObject *self)
56 {
57  Py_DECREF (((thread_object *) self)->inf_obj);
58  Py_TYPE (self)->tp_free (self);
59 }
60 
61 static PyObject *
62 thpy_get_name (PyObject *self, void *ignore)
63 {
65  const char *name;
66 
68 
70  if (name == NULL)
72 
73  if (name == NULL)
74  Py_RETURN_NONE;
75 
76  return PyString_FromString (name);
77 }
78 
79 static int
80 thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore)
81 {
84 
85  if (! thread_obj->thread)
86  {
87  PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists."));
88  return -1;
89  }
90 
91  if (newvalue == NULL)
92  {
93  PyErr_SetString (PyExc_TypeError,
94  _("Cannot delete `name' attribute."));
95  return -1;
96  }
97  else if (newvalue == Py_None)
98  {
99  /* Nothing. */
100  }
101  else if (! gdbpy_is_string (newvalue))
102  {
103  PyErr_SetString (PyExc_TypeError,
104  _("The value of `name' must be a string."));
105  return -1;
106  }
107  else
108  {
109  name = python_string_to_host_string (newvalue);
110  if (! name)
111  return -1;
112  }
113 
115  thread_obj->thread->name = name.release ();
116 
117  return 0;
118 }
119 
120 /* Getter for InferiorThread.num. */
121 
122 static PyObject *
123 thpy_get_num (PyObject *self, void *closure)
124 {
126 
128 
129  return PyLong_FromLong (thread_obj->thread->per_inf_num);
130 }
131 
132 /* Getter for InferiorThread.global_num. */
133 
134 static PyObject *
135 thpy_get_global_num (PyObject *self, void *closure)
136 {
138 
140 
141  return PyLong_FromLong (thread_obj->thread->global_num);
142 }
143 
144 /* Getter for InferiorThread.ptid -> (pid, lwp, tid).
145  Returns a tuple with the thread's ptid components. */
146 
147 static PyObject *
148 thpy_get_ptid (PyObject *self, void *closure)
149 {
151 
153 
155 }
156 
157 /* Getter for InferiorThread.inferior -> Inferior. */
158 
159 static PyObject *
160 thpy_get_inferior (PyObject *self, void *ignore)
161 {
163 
165  Py_INCREF (thread_obj->inf_obj);
166 
167  return thread_obj->inf_obj;
168 }
169 
170 /* Implementation of InferiorThread.switch ().
171  Makes this the GDB selected thread. */
172 
173 static PyObject *
174 thpy_switch (PyObject *self, PyObject *args)
175 {
177 
179 
180  TRY
181  {
183  }
184  CATCH (except, RETURN_MASK_ALL)
185  {
186  GDB_PY_HANDLE_EXCEPTION (except);
187  }
188  END_CATCH
189 
190  Py_RETURN_NONE;
191 }
192 
193 /* Implementation of InferiorThread.is_stopped () -> Boolean.
194  Return whether the thread is stopped. */
195 
196 static PyObject *
197 thpy_is_stopped (PyObject *self, PyObject *args)
198 {
200 
202 
204  Py_RETURN_TRUE;
205 
206  Py_RETURN_FALSE;
207 }
208 
209 /* Implementation of InferiorThread.is_running () -> Boolean.
210  Return whether the thread is running. */
211 
212 static PyObject *
213 thpy_is_running (PyObject *self, PyObject *args)
214 {
216 
218 
220  Py_RETURN_TRUE;
221 
222  Py_RETURN_FALSE;
223 }
224 
225 /* Implementation of InferiorThread.is_exited () -> Boolean.
226  Return whether the thread is exited. */
227 
228 static PyObject *
229 thpy_is_exited (PyObject *self, PyObject *args)
230 {
232 
234 
236  Py_RETURN_TRUE;
237 
238  Py_RETURN_FALSE;
239 }
240 
241 /* Implementation of gdb.InfThread.is_valid (self) -> Boolean.
242  Returns True if this inferior Thread object still exists
243  in GDB. */
244 
245 static PyObject *
246 thpy_is_valid (PyObject *self, PyObject *args)
247 {
249 
250  if (! thread_obj->thread)
251  Py_RETURN_FALSE;
252 
253  Py_RETURN_TRUE;
254 }
255 
256 /* Return a reference to a new Python object representing a ptid_t.
257  The object is a tuple containing (pid, lwp, tid). */
258 PyObject *
260 {
261  int pid;
262  long tid, lwp;
263  PyObject *ret;
264 
265  ret = PyTuple_New (3);
266  if (!ret)
267  return NULL;
268 
269  pid = ptid_get_pid (ptid);
270  lwp = ptid_get_lwp (ptid);
271  tid = ptid_get_tid (ptid);
272 
273  PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid));
274  PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp));
275  PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid));
276 
277  return ret;
278 }
279 
280 /* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
281  Returns the selected thread object. */
282 
283 PyObject *
284 gdbpy_selected_thread (PyObject *self, PyObject *args)
285 {
286  PyObject *thread_obj;
287 
289  if (thread_obj)
290  {
291  Py_INCREF (thread_obj);
292  return thread_obj;
293  }
294 
295  Py_RETURN_NONE;
296 }
297 
298 int
300 {
301  if (PyType_Ready (&thread_object_type) < 0)
302  return -1;
303 
304  return gdb_pymodule_addobject (gdb_module, "InferiorThread",
305  (PyObject *) &thread_object_type);
306 }
307 
309 {
310  { "name", thpy_get_name, thpy_set_name,
311  "The name of the thread, as set by the user or the OS.", NULL },
312  { "num", thpy_get_num, NULL,
313  "Per-inferior number of the thread, as assigned by GDB.", NULL },
314  { "global_num", thpy_get_global_num, NULL,
315  "Global number of the thread, as assigned by GDB.", NULL },
316  { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.",
317  NULL },
318  { "inferior", thpy_get_inferior, NULL,
319  "The Inferior object this thread belongs to.", NULL },
320 
321  { NULL }
322 };
323 
324 static PyMethodDef thread_object_methods[] =
325 {
326  { "is_valid", thpy_is_valid, METH_NOARGS,
327  "is_valid () -> Boolean.\n\
328 Return true if this inferior thread is valid, false if not." },
329  { "switch", thpy_switch, METH_NOARGS,
330  "switch ()\n\
331 Makes this the GDB selected thread." },
332  { "is_stopped", thpy_is_stopped, METH_NOARGS,
333  "is_stopped () -> Boolean\n\
334 Return whether the thread is stopped." },
335  { "is_running", thpy_is_running, METH_NOARGS,
336  "is_running () -> Boolean\n\
337 Return whether the thread is running." },
338  { "is_exited", thpy_is_exited, METH_NOARGS,
339  "is_exited () -> Boolean\n\
340 Return whether the thread is exited." },
341 
342  { NULL }
343 };
344 
345 PyTypeObject thread_object_type =
346 {
347  PyVarObject_HEAD_INIT (NULL, 0)
348  "gdb.InferiorThread", /*tp_name*/
349  sizeof (thread_object), /*tp_basicsize*/
350  0, /*tp_itemsize*/
351  thpy_dealloc, /*tp_dealloc*/
352  0, /*tp_print*/
353  0, /*tp_getattr*/
354  0, /*tp_setattr*/
355  0, /*tp_compare*/
356  0, /*tp_repr*/
357  0, /*tp_as_number*/
358  0, /*tp_as_sequence*/
359  0, /*tp_as_mapping*/
360  0, /*tp_hash */
361  0, /*tp_call*/
362  0, /*tp_str*/
363  0, /*tp_getattro*/
364  0, /*tp_setattro*/
365  0, /*tp_as_buffer*/
366  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
367  "GDB thread object", /* tp_doc */
368  0, /* tp_traverse */
369  0, /* tp_clear */
370  0, /* tp_richcompare */
371  0, /* tp_weaklistoffset */
372  0, /* tp_iter */
373  0, /* tp_iternext */
374  thread_object_methods, /* tp_methods */
375  0, /* tp_members */
376  thread_object_getset, /* tp_getset */
377  0, /* tp_base */
378  0, /* tp_dict */
379  0, /* tp_descr_get */
380  0, /* tp_descr_set */
381  0, /* tp_dictoffset */
382  0, /* tp_init */
383  0 /* tp_alloc */
384 };
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition: py-utils.c:376
static PyObject * thpy_is_exited(PyObject *self, PyObject *args)
Definition: py-infthread.c:229
#define Py_DECREF(op)
static constexpr ptid_t tid
int gdbpy_initialize_thread(void)
Definition: py-infthread.c:299
PyTypeObject thread_object_type
Definition: py-infthread.c:345
static PyMethodDef thread_object_methods[]
Definition: py-infthread.c:324
static PyObject * thpy_get_num(PyObject *self, void *closure)
Definition: py-infthread.c:123
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
Definition: gnu-nat.c:1824
void xfree(void *)
static PyObject * thpy_is_valid(PyObject *self, PyObject *args)
Definition: py-infthread.c:246
thread_object * create_thread_object(struct thread_info *tp)
Definition: py-infthread.c:40
int gdbpy_is_string(PyObject *obj)
Definition: py-utils.c:173
#define _(String)
Definition: gdb_locale.h:35
#define PyVarObject_HEAD_INIT(type, size)
#define END_CATCH
PyObject * inf_obj
static PyObject * thpy_get_ptid(PyObject *self, void *closure)
Definition: py-infthread.c:148
#define GDB_PY_HANDLE_EXCEPTION(Exception)
#define TRY
void switch_to_thread(ptid_t ptid)
Definition: thread.c:1445
const char *const name
Definition: aarch64-tdep.c:76
PyObject * gdbpy_create_ptid_object(ptid_t ptid)
Definition: py-infthread.c:259
int per_inf_num
Definition: gdbthread.h:258
int is_stopped(ptid_t ptid)
Definition: thread.c:963
#define CATCH(EXCEPTION, MASK)
std::unique_ptr< T, xfree_deleter< T > > unique_xmalloc_ptr
long ptid_get_tid(const ptid_t &ptid)
Definition: ptid.c:63
Definition: ptid.h:35
thread_object * find_thread_object(ptid_t ptid)
Definition: py-inferior.c:307
int global_num
Definition: gdbthread.h:253
static PyObject * thpy_is_running(PyObject *self, PyObject *args)
Definition: py-infthread.c:213
ptid_t ptid
Definition: gdbthread.h:219
gdb::unique_xmalloc_ptr< char > python_string_to_host_string(PyObject *obj)
Definition: py-utils.c:152
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
#define THPY_REQUIRE_VALID(Thread)
Definition: py-infthread.c:29
PyObject * gdbpy_selected_thread(PyObject *self, PyObject *args)
Definition: py-infthread.c:284
PyObject_HEAD struct thread_info * thread
const char * target_thread_name(struct thread_info *info)
Definition: target.c:2200
static PyObject * thpy_is_stopped(PyObject *self, PyObject *args)
Definition: py-infthread.c:197
char * name
Definition: gdbthread.h:265
PyTypeObject thread_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("thread_object")
PyObject * find_inferior_object(int pid)
Definition: py-inferior.c:296
static int thpy_set_name(PyObject *self, PyObject *newvalue, void *ignore)
Definition: py-infthread.c:80
ptid_t inferior_ptid
Definition: infcmd.c:94
static constexpr ptid_t lwp
static PyObject * thpy_switch(PyObject *self, PyObject *args)
Definition: py-infthread.c:174
static void thpy_dealloc(PyObject *self)
Definition: py-infthread.c:55
int is_exited(ptid_t ptid)
Definition: thread.c:969
static int ignore(struct target_ops *ops, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
Definition: corelow.c:879
#define Py_TYPE(ob)
PyObject * gdb_module
Definition: python.c:116
thread_object * thread_obj
Definition: py-inferior.c:34
static PyObject * thpy_get_global_num(PyObject *self, void *closure)
Definition: py-infthread.c:135
static PyObject * thpy_get_name(PyObject *self, void *ignore)
Definition: py-infthread.c:62
int is_running(ptid_t ptid)
Definition: thread.c:975
static PyObject * thpy_get_inferior(PyObject *self, void *ignore)
Definition: py-infthread.c:160
static gdb_PyGetSetDef thread_object_getset[]
Definition: py-infthread.c:308