1 /* Python interface to inferiors.
2 
3    Copyright (C) 2009, 2010, 2011 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 "exceptions.h"
22 #include "gdbcore.h"
23 #include "gdbthread.h"
24 #include "inferior.h"
25 #include "observer.h"
26 #include "python-internal.h"
27 #include "arch-utils.h"
28 #include "language.h"
29 #include "gdb_signals.h"
30 #include "py-event.h"
31 #include "py-stopevent.h"
32 
33 struct threadlist_entry {
34   thread_object *thread_obj;
35   struct threadlist_entry *next;
36 };
37 
38 typedef struct
39 {
40   PyObject_HEAD
41 
42   /* The inferior we represent.  */
43   struct inferior *inferior;
44 
45   /* thread_object instances under this inferior.  This list owns a
46      reference to each object it contains.  */
47   struct threadlist_entry *threads;
48 
49   /* Number of threads in the list.  */
50   int nthreads;
51 } inferior_object;
52 
53 static PyTypeObject inferior_object_type;
54 
55 static const struct inferior_data *infpy_inf_data_key;
56 
57 typedef struct {
58   PyObject_HEAD
59   void *buffer;
60 
61   /* These are kept just for mbpy_str.  */
62   CORE_ADDR addr;
63   CORE_ADDR length;
64 } membuf_object;
65 
66 static PyTypeObject membuf_object_type;
67 
68 /* Require that INFERIOR be a valid inferior ID.  */
69 #define INFPY_REQUIRE_VALID(Inferior)				\
70   do {								\
71     if (!Inferior->inferior)					\
72       {								\
73 	PyErr_SetString (PyExc_RuntimeError,			\
74 			 _("Inferior no longer exists."));	\
75 	return NULL;						\
76       }								\
77   } while (0)
78 
79 static void
80 python_on_normal_stop (struct bpstats *bs, int print_frame)
81 {
82   struct cleanup *cleanup;
83   enum target_signal stop_signal;
84 
85   if (!find_thread_ptid (inferior_ptid))
86       return;
87 
88   stop_signal = inferior_thread ()->suspend.stop_signal;
89 
90   cleanup = ensure_python_env (get_current_arch (), current_language);
91 
92   if (emit_stop_event (bs, stop_signal) < 0)
93     gdbpy_print_stack ();
94 
95   do_cleanups (cleanup);
96 }
97 
98 static void
99 python_on_resume (ptid_t ptid)
100 {
101   struct cleanup *cleanup;
102 
103   cleanup = ensure_python_env (target_gdbarch, current_language);
104 
105   if (emit_continue_event (ptid) < 0)
106     gdbpy_print_stack ();
107 
108   do_cleanups (cleanup);
109 }
110 
111 static void
112 python_inferior_exit (struct inferior *inf)
113 {
114   struct cleanup *cleanup;
115   const LONGEST *exit_code = NULL;
116 
117   cleanup = ensure_python_env (target_gdbarch, current_language);
118 
119   if (inf->has_exit_code)
120     exit_code = &inf->exit_code;
121 
122   if (emit_exited_event (exit_code) < 0)
123     gdbpy_print_stack ();
124 
125   do_cleanups (cleanup);
126 }
127 
128 /* Return a borrowed reference to the Python object of type Inferior
129    representing INFERIOR.  If the object has already been created,
130    return it,  otherwise, create it.  Return NULL on failure.  */
131 PyObject *
132 inferior_to_inferior_object (struct inferior *inferior)
133 {
134   inferior_object *inf_obj;
135 
136   inf_obj = inferior_data (inferior, infpy_inf_data_key);
137   if (!inf_obj)
138     {
139       struct cleanup *cleanup;
140       cleanup = ensure_python_env (python_gdbarch, python_language);
141 
142       inf_obj = PyObject_New (inferior_object, &inferior_object_type);
143       if (!inf_obj)
144 	{
145 	  do_cleanups (cleanup);
146 	  return NULL;
147 	}
148 
149       inf_obj->inferior = inferior;
150       inf_obj->threads = NULL;
151       inf_obj->nthreads = 0;
152 
153       set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
154 
155       do_cleanups (cleanup);
156     }
157 
158   return (PyObject *) inf_obj;
159 }
160 
161 /* Finds the Python Inferior object for the given PID.  Returns a
162    borrowed reference, or NULL if PID does not match any inferior
163    object.  */
164 
165 PyObject *
166 find_inferior_object (int pid)
167 {
168   struct inflist_entry *p;
169   struct inferior *inf = find_inferior_pid (pid);
170 
171   if (inf)
172     return inferior_to_inferior_object (inf);
173 
174   return NULL;
175 }
176 
177 thread_object *
178 find_thread_object (ptid_t ptid)
179 {
180   int pid;
181   struct threadlist_entry *thread;
182   PyObject *inf_obj;
183 
184   pid = PIDGET (ptid);
185   if (pid == 0)
186     return NULL;
187 
188   inf_obj = find_inferior_object (pid);
189 
190   if (inf_obj)
191     for (thread = ((inferior_object *)inf_obj)->threads; thread;
192 	 thread = thread->next)
193       if (ptid_equal (thread->thread_obj->thread->ptid, ptid))
194 	return thread->thread_obj;
195 
196   return NULL;
197 }
198 
199 static void
200 add_thread_object (struct thread_info *tp)
201 {
202   struct cleanup *cleanup;
203   thread_object *thread_obj;
204   inferior_object *inf_obj;
205   struct threadlist_entry *entry;
206 
207   cleanup = ensure_python_env (python_gdbarch, python_language);
208 
209   thread_obj = create_thread_object (tp);
210   if (!thread_obj)
211     {
212       gdbpy_print_stack ();
213       do_cleanups (cleanup);
214       return;
215     }
216 
217   inf_obj = (inferior_object *) thread_obj->inf_obj;
218 
219   entry = xmalloc (sizeof (struct threadlist_entry));
220   entry->thread_obj = thread_obj;
221   entry->next = inf_obj->threads;
222 
223   inf_obj->threads = entry;
224   inf_obj->nthreads++;
225 
226   do_cleanups (cleanup);
227 }
228 
229 static void
230 delete_thread_object (struct thread_info *tp, int ignore)
231 {
232   struct cleanup *cleanup;
233   inferior_object *inf_obj;
234   thread_object *thread_obj;
235   struct threadlist_entry **entry, *tmp;
236 
237   inf_obj = (inferior_object *) find_inferior_object (PIDGET(tp->ptid));
238   if (!inf_obj)
239     return;
240 
241   /* Find thread entry in its inferior's thread_list.  */
242   for (entry = &inf_obj->threads; *entry != NULL; entry =
243 	 &(*entry)->next)
244     if ((*entry)->thread_obj->thread == tp)
245       break;
246 
247   if (!*entry)
248     return;
249 
250   cleanup = ensure_python_env (python_gdbarch, python_language);
251 
252   tmp = *entry;
253   tmp->thread_obj->thread = NULL;
254 
255   *entry = (*entry)->next;
256   inf_obj->nthreads--;
257 
258   Py_DECREF (tmp->thread_obj);
259   xfree (tmp);
260 
261   do_cleanups (cleanup);
262 }
263 
264 static PyObject *
265 infpy_threads (PyObject *self, PyObject *args)
266 {
267   int i;
268   struct threadlist_entry *entry;
269   inferior_object *inf_obj = (inferior_object *) self;
270   PyObject *tuple;
271 
272   INFPY_REQUIRE_VALID (inf_obj);
273 
274   tuple = PyTuple_New (inf_obj->nthreads);
275   if (!tuple)
276     return NULL;
277 
278   for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads;
279        i++, entry = entry->next)
280     {
281       Py_INCREF (entry->thread_obj);
282       PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->thread_obj);
283     }
284 
285   return tuple;
286 }
287 
288 static PyObject *
289 infpy_get_num (PyObject *self, void *closure)
290 {
291   inferior_object *inf = (inferior_object *) self;
292 
293   INFPY_REQUIRE_VALID (inf);
294 
295   return PyLong_FromLong (inf->inferior->num);
296 }
297 
298 static PyObject *
299 infpy_get_pid (PyObject *self, void *closure)
300 {
301   inferior_object *inf = (inferior_object *) self;
302 
303   INFPY_REQUIRE_VALID (inf);
304 
305   return PyLong_FromLong (inf->inferior->pid);
306 }
307 
308 static PyObject *
309 infpy_get_was_attached (PyObject *self, void *closure)
310 {
311   inferior_object *inf = (inferior_object *) self;
312 
313   INFPY_REQUIRE_VALID (inf);
314   if (inf->inferior->attach_flag)
315     Py_RETURN_TRUE;
316   Py_RETURN_FALSE;
317 }
318 
319 static int
320 build_inferior_list (struct inferior *inf, void *arg)
321 {
322   PyObject *list = arg;
323   PyObject *inferior = inferior_to_inferior_object (inf);
324 
325   if (PyList_Append (list, inferior))
326     return 1;
327 
328   return 0;
329 }
330 
331 /* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
332    Returns a tuple of all inferiors.  */
333 PyObject *
334 gdbpy_inferiors (PyObject *unused, PyObject *unused2)
335 {
336   int i = 0;
337   PyObject *list, *inferior;
338   struct inferior *inf;
339 
340   list = PyList_New (0);
341   if (!list)
342     return NULL;
343 
344   if (iterate_over_inferiors (build_inferior_list, list))
345     {
346       Py_DECREF (list);
347       return NULL;
348     }
349 
350   return PyList_AsTuple (list);
351 }
352 
353 /* Membuf and memory manipulation.  */
354 
355 /* Implementation of gdb.read_memory (address, length).
356    Returns a Python buffer object with LENGTH bytes of the inferior's
357    memory at ADDRESS.  Both arguments are integers.  Returns NULL on error,
358    with a python exception set.  */
359 static PyObject *
360 infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
361 {
362   int error = 0;
363   CORE_ADDR addr, length;
364   void *buffer = NULL;
365   membuf_object *membuf_obj;
366   PyObject *addr_obj, *length_obj;
367   struct cleanup *cleanups;
368   volatile struct gdb_exception except;
369   static char *keywords[] = { "address", "length", NULL };
370 
371   if (! PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
372 				     &addr_obj, &length_obj))
373     return NULL;
374 
375   cleanups = make_cleanup (null_cleanup, NULL);
376 
377   TRY_CATCH (except, RETURN_MASK_ALL)
378     {
379       if (!get_addr_from_python (addr_obj, &addr)
380 	  || !get_addr_from_python (length_obj, &length))
381 	{
382 	  error = 1;
383 	  break;
384 	}
385 
386       buffer = xmalloc (length);
387       make_cleanup (xfree, buffer);
388 
389       read_memory (addr, buffer, length);
390     }
391   if (except.reason < 0)
392     {
393       do_cleanups (cleanups);
394       GDB_PY_HANDLE_EXCEPTION (except);
395     }
396 
397   if (error)
398     {
399       do_cleanups (cleanups);
400       return NULL;
401     }
402 
403   membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
404   if (membuf_obj == NULL)
405     {
406       PyErr_SetString (PyExc_MemoryError,
407 		       _("Could not allocate memory buffer object."));
408       do_cleanups (cleanups);
409       return NULL;
410     }
411 
412   discard_cleanups (cleanups);
413 
414   membuf_obj->buffer = buffer;
415   membuf_obj->addr = addr;
416   membuf_obj->length = length;
417 
418   return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
419 				       Py_END_OF_BUFFER);
420 }
421 
422 /* Implementation of gdb.write_memory (address, buffer [, length]).
423    Writes the contents of BUFFER (a Python object supporting the read
424    buffer protocol) at ADDRESS in the inferior's memory.  Write LENGTH
425    bytes from BUFFER, or its entire contents if the argument is not
426    provided.  The function returns nothing.  Returns NULL on error, with
427    a python exception set.  */
428 static PyObject *
429 infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
430 {
431   int buf_len, error = 0;
432   const char *buffer;
433   CORE_ADDR addr, length;
434   PyObject *addr_obj, *length_obj = NULL;
435   volatile struct gdb_exception except;
436   static char *keywords[] = { "address", "buffer", "length", NULL };
437 
438 
439   if (! PyArg_ParseTupleAndKeywords (args, kw, "Os#|O", keywords,
440 				     &addr_obj, &buffer, &buf_len,
441 				     &length_obj))
442     return NULL;
443 
444   TRY_CATCH (except, RETURN_MASK_ALL)
445     {
446       if (!get_addr_from_python (addr_obj, &addr))
447 	{
448 	  error = 1;
449 	  break;
450 	}
451 
452       if (!length_obj)
453 	length = buf_len;
454       else if (!get_addr_from_python (length_obj, &length))
455 	{
456 	  error = 1;
457 	  break;
458 	}
459       write_memory (addr, buffer, length);
460     }
461   GDB_PY_HANDLE_EXCEPTION (except);
462 
463   if (error)
464     return NULL;
465 
466   Py_RETURN_NONE;
467 }
468 
469 /* Destructor of Membuf objects.  */
470 static void
471 mbpy_dealloc (PyObject *self)
472 {
473   xfree (((membuf_object *) self)->buffer);
474   self->ob_type->tp_free (self);
475 }
476 
477 /* Return a description of the Membuf object.  */
478 static PyObject *
479 mbpy_str (PyObject *self)
480 {
481   membuf_object *membuf_obj = (membuf_object *) self;
482 
483   return PyString_FromFormat (_("Memory buffer for address %s, \
484 which is %s bytes long."),
485 			      paddress (python_gdbarch, membuf_obj->addr),
486 			      pulongest (membuf_obj->length));
487 }
488 
489 static Py_ssize_t
490 get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
491 {
492   membuf_object *membuf_obj = (membuf_object *) self;
493 
494   if (segment)
495     {
496       PyErr_SetString (PyExc_SystemError,
497 		       _("The memory buffer supports only one segment."));
498       return -1;
499     }
500 
501   *ptrptr = membuf_obj->buffer;
502 
503   return membuf_obj->length;
504 }
505 
506 static Py_ssize_t
507 get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
508 {
509   return get_read_buffer (self, segment, ptrptr);
510 }
511 
512 static Py_ssize_t
513 get_seg_count (PyObject *self, Py_ssize_t *lenp)
514 {
515   if (lenp)
516     *lenp = ((membuf_object *) self)->length;
517 
518   return 1;
519 }
520 
521 static Py_ssize_t
522 get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
523 {
524   void *ptr = NULL;
525   Py_ssize_t ret;
526 
527   ret = get_read_buffer (self, segment, &ptr);
528   *ptrptr = (char *) ptr;
529 
530   return ret;
531 }
532 
533 /* Implementation of
534    gdb.search_memory (address, length, pattern).  ADDRESS is the
535    address to start the search.  LENGTH specifies the scope of the
536    search from ADDRESS.  PATTERN is the pattern to search for (and
537    must be a Python object supporting the buffer protocol).
538    Returns a Python Long object holding the address where the pattern
539    was located, or if the pattern was not found, returns None.  Returns NULL
540    on error, with a python exception set.  */
541 static PyObject *
542 infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
543 {
544   CORE_ADDR start_addr, length;
545   static char *keywords[] = { "address", "length", "pattern", NULL };
546   PyObject *pattern, *start_addr_obj, *length_obj;
547   volatile struct gdb_exception except;
548   Py_ssize_t pattern_size;
549   const void *buffer;
550   CORE_ADDR found_addr;
551   int found = 0;
552 
553   if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO", keywords,
554 				     &start_addr_obj, &length_obj,
555 				     &pattern))
556     return NULL;
557 
558   if (get_addr_from_python (start_addr_obj, &start_addr)
559       && get_addr_from_python (length_obj, &length))
560     {
561       if (!length)
562 	{
563 	  PyErr_SetString (PyExc_ValueError,
564 			   _("Search range is empty."));
565 	  return NULL;
566 	}
567       /* Watch for overflows.  */
568       else if (length > CORE_ADDR_MAX
569 	       || (start_addr + length - 1) < start_addr)
570 	{
571 	  PyErr_SetString (PyExc_ValueError,
572 			   _("The search range is too large."));
573 
574 	  return NULL;
575 	}
576     }
577   else
578     return NULL;
579 
580   if (!PyObject_CheckReadBuffer (pattern))
581     {
582       PyErr_SetString (PyExc_RuntimeError,
583 		       _("The pattern is not a Python buffer."));
584 
585       return NULL;
586     }
587 
588   if (PyObject_AsReadBuffer (pattern, &buffer, &pattern_size) == -1)
589     return NULL;
590 
591   TRY_CATCH (except, RETURN_MASK_ALL)
592     {
593       found = target_search_memory (start_addr, length,
594 				    buffer, pattern_size,
595 				    &found_addr);
596     }
597   GDB_PY_HANDLE_EXCEPTION (except);
598 
599   if (found)
600     return PyLong_FromLong (found_addr);
601   else
602     Py_RETURN_NONE;
603 }
604 
605 /* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
606    Returns True if this inferior object still exists in GDB.  */
607 
608 static PyObject *
609 infpy_is_valid (PyObject *self, PyObject *args)
610 {
611   inferior_object *inf = (inferior_object *) self;
612 
613   if (! inf->inferior)
614     Py_RETURN_FALSE;
615 
616   Py_RETURN_TRUE;
617 }
618 
619 
620 /* Clear the INFERIOR pointer in an Inferior object and clear the
621    thread list.  */
622 static void
623 py_free_inferior (struct inferior *inf, void *datum)
624 {
625 
626   struct cleanup *cleanup;
627   inferior_object *inf_obj = datum;
628   struct threadlist_entry *th_entry, *th_tmp;
629 
630   cleanup = ensure_python_env (python_gdbarch, python_language);
631 
632   inf_obj->inferior = NULL;
633 
634   /* Deallocate threads list.  */
635   for (th_entry = inf_obj->threads; th_entry != NULL;)
636     {
637       Py_DECREF (th_entry->thread_obj);
638 
639       th_tmp = th_entry;
640       th_entry = th_entry->next;
641       xfree (th_tmp);
642     }
643 
644   inf_obj->nthreads = 0;
645 
646   Py_DECREF ((PyObject *) inf_obj);
647   do_cleanups (cleanup);
648 }
649 
650 void
651 gdbpy_initialize_inferior (void)
652 {
653   if (PyType_Ready (&inferior_object_type) < 0)
654     return;
655 
656   Py_INCREF (&inferior_object_type);
657   PyModule_AddObject (gdb_module, "Inferior",
658 		      (PyObject *) &inferior_object_type);
659 
660   infpy_inf_data_key =
661     register_inferior_data_with_cleanup (py_free_inferior);
662 
663   observer_attach_new_thread (add_thread_object);
664   observer_attach_thread_exit (delete_thread_object);
665   observer_attach_normal_stop (python_on_normal_stop);
666   observer_attach_target_resumed (python_on_resume);
667   observer_attach_inferior_exit (python_inferior_exit);
668 
669   if (PyType_Ready (&membuf_object_type) < 0)
670     return;
671 
672   Py_INCREF (&membuf_object_type);
673   PyModule_AddObject (gdb_module, "Membuf", (PyObject *)
674 		      &membuf_object_type);
675 }
676 
677 static PyGetSetDef inferior_object_getset[] =
678 {
679   { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
680   { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
681     NULL },
682   { "was_attached", infpy_get_was_attached, NULL,
683     "True if the inferior was created using 'attach'.", NULL },
684   { NULL }
685 };
686 
687 static PyMethodDef inferior_object_methods[] =
688 {
689   { "is_valid", infpy_is_valid, METH_NOARGS,
690     "is_valid () -> Boolean.\n\
691 Return true if this inferior is valid, false if not." },
692   { "threads", infpy_threads, METH_NOARGS,
693     "Return all the threads of this inferior." },
694   { "read_memory", (PyCFunction) infpy_read_memory,
695     METH_VARARGS | METH_KEYWORDS,
696     "read_memory (address, length) -> buffer\n\
697 Return a buffer object for reading from the inferior's memory." },
698   { "write_memory", (PyCFunction) infpy_write_memory,
699     METH_VARARGS | METH_KEYWORDS,
700     "write_memory (address, buffer [, length])\n\
701 Write the given buffer object to the inferior's memory." },
702   { "search_memory", (PyCFunction) infpy_search_memory,
703     METH_VARARGS | METH_KEYWORDS,
704     "search_memory (address, length, pattern) -> long\n\
705 Return a long with the address of a match, or None." },
706   { NULL }
707 };
708 
709 static PyTypeObject inferior_object_type =
710 {
711   PyObject_HEAD_INIT (NULL)
712   0,				  /* ob_size */
713   "gdb.Inferior",		  /* tp_name */
714   sizeof (inferior_object),	  /* tp_basicsize */
715   0,				  /* tp_itemsize */
716   0,				  /* tp_dealloc */
717   0,				  /* tp_print */
718   0,				  /* tp_getattr */
719   0,				  /* tp_setattr */
720   0,				  /* tp_compare */
721   0,				  /* tp_repr */
722   0,				  /* tp_as_number */
723   0,				  /* tp_as_sequence */
724   0,				  /* tp_as_mapping */
725   0,				  /* tp_hash  */
726   0,				  /* tp_call */
727   0,				  /* tp_str */
728   0,				  /* tp_getattro */
729   0,				  /* tp_setattro */
730   0,				  /* tp_as_buffer */
731   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /* tp_flags */
732   "GDB inferior object",	  /* tp_doc */
733   0,				  /* tp_traverse */
734   0,				  /* tp_clear */
735   0,				  /* tp_richcompare */
736   0,				  /* tp_weaklistoffset */
737   0,				  /* tp_iter */
738   0,				  /* tp_iternext */
739   inferior_object_methods,	  /* tp_methods */
740   0,				  /* tp_members */
741   inferior_object_getset,	  /* tp_getset */
742   0,				  /* tp_base */
743   0,				  /* tp_dict */
744   0,				  /* tp_descr_get */
745   0,				  /* tp_descr_set */
746   0,				  /* tp_dictoffset */
747   0,				  /* tp_init */
748   0				  /* tp_alloc */
749 };
750 
751 /* Python doesn't provide a decent way to get compatibility here.  */
752 #if HAVE_LIBPYTHON2_4
753 #define CHARBUFFERPROC_NAME getcharbufferproc
754 #else
755 #define CHARBUFFERPROC_NAME charbufferproc
756 #endif
757 
758 static PyBufferProcs buffer_procs = {
759   get_read_buffer,
760   get_write_buffer,
761   get_seg_count,
762   /* The cast here works around a difference between Python 2.4 and
763      Python 2.5.  */
764   (CHARBUFFERPROC_NAME) get_char_buffer
765 };
766 
767 static PyTypeObject membuf_object_type = {
768   PyObject_HEAD_INIT (NULL)
769   0,				  /*ob_size*/
770   "gdb.Membuf",			  /*tp_name*/
771   sizeof (membuf_object),	  /*tp_basicsize*/
772   0,				  /*tp_itemsize*/
773   mbpy_dealloc,			  /*tp_dealloc*/
774   0,				  /*tp_print*/
775   0,				  /*tp_getattr*/
776   0,				  /*tp_setattr*/
777   0,				  /*tp_compare*/
778   0,				  /*tp_repr*/
779   0,				  /*tp_as_number*/
780   0,				  /*tp_as_sequence*/
781   0,				  /*tp_as_mapping*/
782   0,				  /*tp_hash */
783   0,				  /*tp_call*/
784   mbpy_str,			  /*tp_str*/
785   0,				  /*tp_getattro*/
786   0,				  /*tp_setattro*/
787   &buffer_procs,		  /*tp_as_buffer*/
788   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
789   "GDB memory buffer object", 	  /*tp_doc*/
790   0,				  /* tp_traverse */
791   0,				  /* tp_clear */
792   0,				  /* tp_richcompare */
793   0,				  /* tp_weaklistoffset */
794   0,				  /* tp_iter */
795   0,				  /* tp_iternext */
796   0,				  /* tp_methods */
797   0,				  /* tp_members */
798   0,				  /* tp_getset */
799   0,				  /* tp_base */
800   0,				  /* tp_dict */
801   0,				  /* tp_descr_get */
802   0,				  /* tp_descr_set */
803   0,				  /* tp_dictoffset */
804   0,				  /* tp_init */
805   0,				  /* tp_alloc */
806   PyType_GenericNew		  /* tp_new */
807 };
808