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