1 /* Python interface to stack frames 2 3 Copyright (C) 2008-2014 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 "charset.h" 22 #include "block.h" 23 #include "frame.h" 24 #include "exceptions.h" 25 #include "symtab.h" 26 #include "stack.h" 27 #include "value.h" 28 #include "python-internal.h" 29 #include "symfile.h" 30 #include "objfiles.h" 31 32 typedef struct { 33 PyObject_HEAD 34 struct frame_id frame_id; 35 struct gdbarch *gdbarch; 36 37 /* Marks that the FRAME_ID member actually holds the ID of the frame next 38 to this, and not this frames' ID itself. This is a hack to permit Python 39 frame objects which represent invalid frames (i.e., the last frame_info 40 in a corrupt stack). The problem arises from the fact that this code 41 relies on FRAME_ID to uniquely identify a frame, which is not always true 42 for the last "frame" in a corrupt stack (it can have a null ID, or the same 43 ID as the previous frame). Whenever get_prev_frame returns NULL, we 44 record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */ 45 int frame_id_is_next; 46 } frame_object; 47 48 /* Require a valid frame. This must be called inside a TRY_CATCH, or 49 another context in which a gdb exception is allowed. */ 50 #define FRAPY_REQUIRE_VALID(frame_obj, frame) \ 51 do { \ 52 frame = frame_object_to_frame_info (frame_obj); \ 53 if (frame == NULL) \ 54 error (_("Frame is invalid.")); \ 55 } while (0) 56 57 /* Returns the frame_info object corresponding to the given Python Frame 58 object. If the frame doesn't exist anymore (the frame id doesn't 59 correspond to any frame in the inferior), returns NULL. */ 60 61 struct frame_info * 62 frame_object_to_frame_info (PyObject *obj) 63 { 64 frame_object *frame_obj = (frame_object *) obj; 65 struct frame_info *frame; 66 67 frame = frame_find_by_id (frame_obj->frame_id); 68 if (frame == NULL) 69 return NULL; 70 71 if (frame_obj->frame_id_is_next) 72 frame = get_prev_frame (frame); 73 74 return frame; 75 } 76 77 /* Called by the Python interpreter to obtain string representation 78 of the object. */ 79 80 static PyObject * 81 frapy_str (PyObject *self) 82 { 83 char *s; 84 PyObject *result; 85 struct ui_file *strfile; 86 87 strfile = mem_fileopen (); 88 fprint_frame_id (strfile, ((frame_object *) self)->frame_id); 89 s = ui_file_xstrdup (strfile, NULL); 90 result = PyString_FromString (s); 91 xfree (s); 92 93 return result; 94 } 95 96 /* Implementation of gdb.Frame.is_valid (self) -> Boolean. 97 Returns True if the frame corresponding to the frame_id of this 98 object still exists in the inferior. */ 99 100 static PyObject * 101 frapy_is_valid (PyObject *self, PyObject *args) 102 { 103 struct frame_info *frame = NULL; 104 volatile struct gdb_exception except; 105 106 TRY_CATCH (except, RETURN_MASK_ALL) 107 { 108 frame = frame_object_to_frame_info (self); 109 } 110 GDB_PY_HANDLE_EXCEPTION (except); 111 112 if (frame == NULL) 113 Py_RETURN_FALSE; 114 115 Py_RETURN_TRUE; 116 } 117 118 /* Implementation of gdb.Frame.name (self) -> String. 119 Returns the name of the function corresponding to this frame. */ 120 121 static PyObject * 122 frapy_name (PyObject *self, PyObject *args) 123 { 124 struct frame_info *frame; 125 char *name = NULL; 126 enum language lang; 127 PyObject *result; 128 volatile struct gdb_exception except; 129 130 TRY_CATCH (except, RETURN_MASK_ALL) 131 { 132 FRAPY_REQUIRE_VALID (self, frame); 133 134 find_frame_funname (frame, &name, &lang, NULL); 135 } 136 137 if (except.reason < 0) 138 xfree (name); 139 140 GDB_PY_HANDLE_EXCEPTION (except); 141 142 if (name) 143 { 144 result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL); 145 xfree (name); 146 } 147 else 148 { 149 result = Py_None; 150 Py_INCREF (Py_None); 151 } 152 153 return result; 154 } 155 156 /* Implementation of gdb.Frame.type (self) -> Integer. 157 Returns the frame type, namely one of the gdb.*_FRAME constants. */ 158 159 static PyObject * 160 frapy_type (PyObject *self, PyObject *args) 161 { 162 struct frame_info *frame; 163 enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */ 164 volatile struct gdb_exception except; 165 166 TRY_CATCH (except, RETURN_MASK_ALL) 167 { 168 FRAPY_REQUIRE_VALID (self, frame); 169 170 type = get_frame_type (frame); 171 } 172 GDB_PY_HANDLE_EXCEPTION (except); 173 174 return PyInt_FromLong (type); 175 } 176 177 /* Implementation of gdb.Frame.architecture (self) -> gdb.Architecture. 178 Returns the frame's architecture as a gdb.Architecture object. */ 179 180 static PyObject * 181 frapy_arch (PyObject *self, PyObject *args) 182 { 183 struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */ 184 frame_object *obj = (frame_object *) self; 185 volatile struct gdb_exception except; 186 187 TRY_CATCH (except, RETURN_MASK_ALL) 188 { 189 FRAPY_REQUIRE_VALID (self, frame); 190 } 191 GDB_PY_HANDLE_EXCEPTION (except); 192 193 return gdbarch_to_arch_object (obj->gdbarch); 194 } 195 196 /* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer. 197 Returns one of the gdb.FRAME_UNWIND_* constants. */ 198 199 static PyObject * 200 frapy_unwind_stop_reason (PyObject *self, PyObject *args) 201 { 202 struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */ 203 volatile struct gdb_exception except; 204 enum unwind_stop_reason stop_reason; 205 206 TRY_CATCH (except, RETURN_MASK_ALL) 207 { 208 FRAPY_REQUIRE_VALID (self, frame); 209 } 210 GDB_PY_HANDLE_EXCEPTION (except); 211 212 stop_reason = get_frame_unwind_stop_reason (frame); 213 214 return PyInt_FromLong (stop_reason); 215 } 216 217 /* Implementation of gdb.Frame.pc (self) -> Long. 218 Returns the frame's resume address. */ 219 220 static PyObject * 221 frapy_pc (PyObject *self, PyObject *args) 222 { 223 CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */ 224 struct frame_info *frame; 225 volatile struct gdb_exception except; 226 227 TRY_CATCH (except, RETURN_MASK_ALL) 228 { 229 FRAPY_REQUIRE_VALID (self, frame); 230 231 pc = get_frame_pc (frame); 232 } 233 GDB_PY_HANDLE_EXCEPTION (except); 234 235 return gdb_py_long_from_ulongest (pc); 236 } 237 238 /* Implementation of gdb.Frame.block (self) -> gdb.Block. 239 Returns the frame's code block. */ 240 241 static PyObject * 242 frapy_block (PyObject *self, PyObject *args) 243 { 244 struct frame_info *frame; 245 struct block *block = NULL, *fn_block; 246 volatile struct gdb_exception except; 247 248 TRY_CATCH (except, RETURN_MASK_ALL) 249 { 250 FRAPY_REQUIRE_VALID (self, frame); 251 block = get_frame_block (frame, NULL); 252 } 253 GDB_PY_HANDLE_EXCEPTION (except); 254 255 for (fn_block = block; 256 fn_block != NULL && BLOCK_FUNCTION (fn_block) == NULL; 257 fn_block = BLOCK_SUPERBLOCK (fn_block)) 258 ; 259 260 if (block == NULL || fn_block == NULL || BLOCK_FUNCTION (fn_block) == NULL) 261 { 262 PyErr_SetString (PyExc_RuntimeError, 263 _("Cannot locate block for frame.")); 264 return NULL; 265 } 266 267 if (block) 268 { 269 struct symtab *symt; 270 271 symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block)); 272 return block_to_block_object (block, symt->objfile); 273 } 274 275 Py_RETURN_NONE; 276 } 277 278 279 /* Implementation of gdb.Frame.function (self) -> gdb.Symbol. 280 Returns the symbol for the function corresponding to this frame. */ 281 282 static PyObject * 283 frapy_function (PyObject *self, PyObject *args) 284 { 285 struct symbol *sym = NULL; 286 struct frame_info *frame; 287 volatile struct gdb_exception except; 288 289 TRY_CATCH (except, RETURN_MASK_ALL) 290 { 291 FRAPY_REQUIRE_VALID (self, frame); 292 293 sym = find_pc_function (get_frame_address_in_block (frame)); 294 } 295 GDB_PY_HANDLE_EXCEPTION (except); 296 297 if (sym) 298 return symbol_to_symbol_object (sym); 299 300 Py_RETURN_NONE; 301 } 302 303 /* Convert a frame_info struct to a Python Frame object. 304 Sets a Python exception and returns NULL on error. */ 305 306 PyObject * 307 frame_info_to_frame_object (struct frame_info *frame) 308 { 309 frame_object *frame_obj; 310 volatile struct gdb_exception except; 311 312 frame_obj = PyObject_New (frame_object, &frame_object_type); 313 if (frame_obj == NULL) 314 return NULL; 315 316 TRY_CATCH (except, RETURN_MASK_ALL) 317 { 318 319 /* Try to get the previous frame, to determine if this is the last frame 320 in a corrupt stack. If so, we need to store the frame_id of the next 321 frame and not of this one (which is possibly invalid). */ 322 if (get_prev_frame (frame) == NULL 323 && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON 324 && get_next_frame (frame) != NULL) 325 { 326 frame_obj->frame_id = get_frame_id (get_next_frame (frame)); 327 frame_obj->frame_id_is_next = 1; 328 } 329 else 330 { 331 frame_obj->frame_id = get_frame_id (frame); 332 frame_obj->frame_id_is_next = 0; 333 } 334 frame_obj->gdbarch = get_frame_arch (frame); 335 } 336 if (except.reason < 0) 337 { 338 Py_DECREF (frame_obj); 339 gdbpy_convert_exception (except); 340 return NULL; 341 } 342 return (PyObject *) frame_obj; 343 } 344 345 /* Implementation of gdb.Frame.older (self) -> gdb.Frame. 346 Returns the frame immediately older (outer) to this frame, or None if 347 there isn't one. */ 348 349 static PyObject * 350 frapy_older (PyObject *self, PyObject *args) 351 { 352 struct frame_info *frame, *prev = NULL; 353 volatile struct gdb_exception except; 354 PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */ 355 356 TRY_CATCH (except, RETURN_MASK_ALL) 357 { 358 FRAPY_REQUIRE_VALID (self, frame); 359 360 prev = get_prev_frame (frame); 361 } 362 GDB_PY_HANDLE_EXCEPTION (except); 363 364 if (prev) 365 prev_obj = (PyObject *) frame_info_to_frame_object (prev); 366 else 367 { 368 Py_INCREF (Py_None); 369 prev_obj = Py_None; 370 } 371 372 return prev_obj; 373 } 374 375 /* Implementation of gdb.Frame.newer (self) -> gdb.Frame. 376 Returns the frame immediately newer (inner) to this frame, or None if 377 there isn't one. */ 378 379 static PyObject * 380 frapy_newer (PyObject *self, PyObject *args) 381 { 382 struct frame_info *frame, *next = NULL; 383 volatile struct gdb_exception except; 384 PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */ 385 386 TRY_CATCH (except, RETURN_MASK_ALL) 387 { 388 FRAPY_REQUIRE_VALID (self, frame); 389 390 next = get_next_frame (frame); 391 } 392 GDB_PY_HANDLE_EXCEPTION (except); 393 394 if (next) 395 next_obj = (PyObject *) frame_info_to_frame_object (next); 396 else 397 { 398 Py_INCREF (Py_None); 399 next_obj = Py_None; 400 } 401 402 return next_obj; 403 } 404 405 /* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line. 406 Returns the frame's symtab and line. */ 407 408 static PyObject * 409 frapy_find_sal (PyObject *self, PyObject *args) 410 { 411 struct frame_info *frame; 412 struct symtab_and_line sal; 413 volatile struct gdb_exception except; 414 PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */ 415 416 TRY_CATCH (except, RETURN_MASK_ALL) 417 { 418 FRAPY_REQUIRE_VALID (self, frame); 419 420 find_frame_sal (frame, &sal); 421 sal_obj = symtab_and_line_to_sal_object (sal); 422 } 423 GDB_PY_HANDLE_EXCEPTION (except); 424 425 return sal_obj; 426 } 427 428 /* Implementation of gdb.Frame.read_var_value (self, variable, 429 [block]) -> gdb.Value. If the optional block argument is provided 430 start the search from that block, otherwise search from the frame's 431 current block (determined by examining the resume address of the 432 frame). The variable argument must be a string or an instance of a 433 gdb.Symbol. The block argument must be an instance of gdb.Block. Returns 434 NULL on error, with a python exception set. */ 435 static PyObject * 436 frapy_read_var (PyObject *self, PyObject *args) 437 { 438 struct frame_info *frame; 439 PyObject *sym_obj, *block_obj = NULL; 440 struct symbol *var = NULL; /* gcc-4.3.2 false warning. */ 441 struct value *val = NULL; 442 volatile struct gdb_exception except; 443 444 if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj)) 445 return NULL; 446 447 if (PyObject_TypeCheck (sym_obj, &symbol_object_type)) 448 var = symbol_object_to_symbol (sym_obj); 449 else if (gdbpy_is_string (sym_obj)) 450 { 451 char *var_name; 452 const struct block *block = NULL; 453 struct cleanup *cleanup; 454 volatile struct gdb_exception except; 455 456 var_name = python_string_to_target_string (sym_obj); 457 if (!var_name) 458 return NULL; 459 cleanup = make_cleanup (xfree, var_name); 460 461 if (block_obj) 462 { 463 block = block_object_to_block (block_obj); 464 if (!block) 465 { 466 PyErr_SetString (PyExc_RuntimeError, 467 _("Second argument must be block.")); 468 do_cleanups (cleanup); 469 return NULL; 470 } 471 } 472 473 TRY_CATCH (except, RETURN_MASK_ALL) 474 { 475 FRAPY_REQUIRE_VALID (self, frame); 476 477 if (!block) 478 block = get_frame_block (frame, NULL); 479 var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); 480 } 481 if (except.reason < 0) 482 { 483 do_cleanups (cleanup); 484 gdbpy_convert_exception (except); 485 return NULL; 486 } 487 488 if (!var) 489 { 490 PyErr_Format (PyExc_ValueError, 491 _("Variable '%s' not found."), var_name); 492 do_cleanups (cleanup); 493 494 return NULL; 495 } 496 497 do_cleanups (cleanup); 498 } 499 else 500 { 501 PyErr_SetString (PyExc_TypeError, 502 _("Argument must be a symbol or string.")); 503 return NULL; 504 } 505 506 TRY_CATCH (except, RETURN_MASK_ALL) 507 { 508 FRAPY_REQUIRE_VALID (self, frame); 509 510 val = read_var_value (var, frame); 511 } 512 GDB_PY_HANDLE_EXCEPTION (except); 513 514 return value_to_value_object (val); 515 } 516 517 /* Select this frame. */ 518 519 static PyObject * 520 frapy_select (PyObject *self, PyObject *args) 521 { 522 struct frame_info *fi; 523 volatile struct gdb_exception except; 524 525 TRY_CATCH (except, RETURN_MASK_ALL) 526 { 527 FRAPY_REQUIRE_VALID (self, fi); 528 529 select_frame (fi); 530 } 531 GDB_PY_HANDLE_EXCEPTION (except); 532 533 Py_RETURN_NONE; 534 } 535 536 /* Implementation of gdb.newest_frame () -> gdb.Frame. 537 Returns the newest frame object. */ 538 539 PyObject * 540 gdbpy_newest_frame (PyObject *self, PyObject *args) 541 { 542 struct frame_info *frame = NULL; 543 volatile struct gdb_exception except; 544 545 TRY_CATCH (except, RETURN_MASK_ALL) 546 { 547 frame = get_current_frame (); 548 } 549 GDB_PY_HANDLE_EXCEPTION (except); 550 551 return frame_info_to_frame_object (frame); 552 } 553 554 /* Implementation of gdb.selected_frame () -> gdb.Frame. 555 Returns the selected frame object. */ 556 557 PyObject * 558 gdbpy_selected_frame (PyObject *self, PyObject *args) 559 { 560 struct frame_info *frame = NULL; 561 volatile struct gdb_exception except; 562 563 TRY_CATCH (except, RETURN_MASK_ALL) 564 { 565 frame = get_selected_frame ("No frame is currently selected."); 566 } 567 GDB_PY_HANDLE_EXCEPTION (except); 568 569 return frame_info_to_frame_object (frame); 570 } 571 572 /* Implementation of gdb.stop_reason_string (Integer) -> String. 573 Return a string explaining the unwind stop reason. */ 574 575 PyObject * 576 gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args) 577 { 578 int reason; 579 const char *str; 580 581 if (!PyArg_ParseTuple (args, "i", &reason)) 582 return NULL; 583 584 if (reason < UNWIND_FIRST || reason > UNWIND_LAST) 585 { 586 PyErr_SetString (PyExc_ValueError, 587 _("Invalid frame stop reason.")); 588 return NULL; 589 } 590 591 str = frame_stop_reason_string (reason); 592 return PyUnicode_Decode (str, strlen (str), host_charset (), NULL); 593 } 594 595 /* Implements the equality comparison for Frame objects. 596 All other comparison operators will throw a TypeError Python exception, 597 as they aren't valid for frames. */ 598 599 static PyObject * 600 frapy_richcompare (PyObject *self, PyObject *other, int op) 601 { 602 int result; 603 604 if (!PyObject_TypeCheck (other, &frame_object_type) 605 || (op != Py_EQ && op != Py_NE)) 606 { 607 Py_INCREF (Py_NotImplemented); 608 return Py_NotImplemented; 609 } 610 611 if (frame_id_eq (((frame_object *) self)->frame_id, 612 ((frame_object *) other)->frame_id)) 613 result = Py_EQ; 614 else 615 result = Py_NE; 616 617 if (op == result) 618 Py_RETURN_TRUE; 619 Py_RETURN_FALSE; 620 } 621 622 /* Sets up the Frame API in the gdb module. */ 623 624 int 625 gdbpy_initialize_frames (void) 626 { 627 frame_object_type.tp_new = PyType_GenericNew; 628 if (PyType_Ready (&frame_object_type) < 0) 629 return -1; 630 631 /* Note: These would probably be best exposed as class attributes of 632 Frame, but I don't know how to do it except by messing with the 633 type's dictionary. That seems too messy. */ 634 if (PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME) < 0 635 || PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME) < 0 636 || PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME) < 0 637 || PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", 638 TAILCALL_FRAME) < 0 639 || PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", 640 SIGTRAMP_FRAME) < 0 641 || PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME) < 0 642 || PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", 643 SENTINEL_FRAME) < 0) 644 return -1; 645 646 #define SET(name, description) \ 647 if (PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name) < 0) \ 648 return -1; 649 #include "unwind_stop_reasons.def" 650 #undef SET 651 652 return gdb_pymodule_addobject (gdb_module, "Frame", 653 (PyObject *) &frame_object_type); 654 } 655 656 657 658 static PyMethodDef frame_object_methods[] = { 659 { "is_valid", frapy_is_valid, METH_NOARGS, 660 "is_valid () -> Boolean.\n\ 661 Return true if this frame is valid, false if not." }, 662 { "name", frapy_name, METH_NOARGS, 663 "name () -> String.\n\ 664 Return the function name of the frame, or None if it can't be determined." }, 665 { "type", frapy_type, METH_NOARGS, 666 "type () -> Integer.\n\ 667 Return the type of the frame." }, 668 { "architecture", frapy_arch, METH_NOARGS, 669 "architecture () -> gdb.Architecture.\n\ 670 Return the architecture of the frame." }, 671 { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS, 672 "unwind_stop_reason () -> Integer.\n\ 673 Return the reason why it's not possible to find frames older than this." }, 674 { "pc", frapy_pc, METH_NOARGS, 675 "pc () -> Long.\n\ 676 Return the frame's resume address." }, 677 { "block", frapy_block, METH_NOARGS, 678 "block () -> gdb.Block.\n\ 679 Return the frame's code block." }, 680 { "function", frapy_function, METH_NOARGS, 681 "function () -> gdb.Symbol.\n\ 682 Returns the symbol for the function corresponding to this frame." }, 683 { "older", frapy_older, METH_NOARGS, 684 "older () -> gdb.Frame.\n\ 685 Return the frame that called this frame." }, 686 { "newer", frapy_newer, METH_NOARGS, 687 "newer () -> gdb.Frame.\n\ 688 Return the frame called by this frame." }, 689 { "find_sal", frapy_find_sal, METH_NOARGS, 690 "find_sal () -> gdb.Symtab_and_line.\n\ 691 Return the frame's symtab and line." }, 692 { "read_var", frapy_read_var, METH_VARARGS, 693 "read_var (variable) -> gdb.Value.\n\ 694 Return the value of the variable in this frame." }, 695 { "select", frapy_select, METH_NOARGS, 696 "Select this frame as the user's current frame." }, 697 {NULL} /* Sentinel */ 698 }; 699 700 PyTypeObject frame_object_type = { 701 PyVarObject_HEAD_INIT (NULL, 0) 702 "gdb.Frame", /* tp_name */ 703 sizeof (frame_object), /* tp_basicsize */ 704 0, /* tp_itemsize */ 705 0, /* tp_dealloc */ 706 0, /* tp_print */ 707 0, /* tp_getattr */ 708 0, /* tp_setattr */ 709 0, /* tp_compare */ 710 0, /* tp_repr */ 711 0, /* tp_as_number */ 712 0, /* tp_as_sequence */ 713 0, /* tp_as_mapping */ 714 0, /* tp_hash */ 715 0, /* tp_call */ 716 frapy_str, /* tp_str */ 717 0, /* tp_getattro */ 718 0, /* tp_setattro */ 719 0, /* tp_as_buffer */ 720 Py_TPFLAGS_DEFAULT, /* tp_flags */ 721 "GDB frame object", /* tp_doc */ 722 0, /* tp_traverse */ 723 0, /* tp_clear */ 724 frapy_richcompare, /* tp_richcompare */ 725 0, /* tp_weaklistoffset */ 726 0, /* tp_iter */ 727 0, /* tp_iternext */ 728 frame_object_methods, /* tp_methods */ 729 0, /* tp_members */ 730 0, /* tp_getset */ 731 0, /* tp_base */ 732 0, /* tp_dict */ 733 0, /* tp_descr_get */ 734 0, /* tp_descr_set */ 735 0, /* tp_dictoffset */ 736 0, /* tp_init */ 737 0, /* tp_alloc */ 738 }; 739