Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / python / py-block.c
index 8d7fb79231146093f91419144374ad5331178e5d..26d59e102a37860ebc5a2f3c836b76aea5e22cc5 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to blocks.
 
-   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "symtab.h"
 #include "python-internal.h"
 #include "objfiles.h"
-#include "symtab.h"
 
 typedef struct blpy_block_object {
   PyObject_HEAD
   /* The GDB block structure that represents a frame's code block.  */
-  struct block *block;
+  const struct block *block;
   /* The backing object file.  There is no direct relationship in GDB
      between a block and an object file.  When a block is created also
      store a pointer to the object file for later use.  */
@@ -41,10 +40,10 @@ typedef struct blpy_block_object {
 
 typedef struct {
   PyObject_HEAD
-  /* The block dictionary of symbols.  */
-  struct dictionary *dict;
-  /* The iterator for that dictionary.  */
-  struct dict_iterator iter;
+  /* The block.  */
+  const struct block *block;
+  /* The iterator for that block.  */
+  struct block_iterator iter;
   /* Has the iterator been initialized flag.  */
   int initialized_p;
   /* Pointer back to the original source block object.  Needed to
@@ -78,14 +77,15 @@ typedef struct {
       }                                                                        \
   } while (0)
 
-static PyTypeObject block_syms_iterator_object_type;
+extern PyTypeObject block_syms_iterator_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("block_syms_iterator_object");
 static const struct objfile_data *blpy_objfile_data_key;
 
 static PyObject *
 blpy_iter (PyObject *self)
 {
   block_syms_iterator_object *block_iter_obj;
-  struct block *block = NULL;
+  const struct block *block = NULL;
 
   BLPY_REQUIRE_VALID (self, block);
 
@@ -94,7 +94,7 @@ blpy_iter (PyObject *self)
   if (block_iter_obj == NULL)
       return NULL;
 
-  block_iter_obj->dict = BLOCK_DICT (block);
+  block_iter_obj->block = block;
   block_iter_obj->initialized_p = 0;
   Py_INCREF (self);
   block_iter_obj->source = (block_object *) self;
@@ -105,28 +105,28 @@ blpy_iter (PyObject *self)
 static PyObject *
 blpy_get_start (PyObject *self, void *closure)
 {
-  struct block *block = NULL;
+  const struct block *block = NULL;
 
   BLPY_REQUIRE_VALID (self, block);
 
-  return PyLong_FromUnsignedLongLong (BLOCK_START (block));
+  return gdb_py_object_from_ulongest (BLOCK_START (block)).release ();
 }
 
 static PyObject *
 blpy_get_end (PyObject *self, void *closure)
 {
-  struct block *block = NULL;
+  const struct block *block = NULL;
 
   BLPY_REQUIRE_VALID (self, block);
 
-  return PyLong_FromUnsignedLongLong (BLOCK_END (block));
+  return gdb_py_object_from_ulongest (BLOCK_END (block)).release ();
 }
 
 static PyObject *
 blpy_get_function (PyObject *self, void *closure)
 {
   struct symbol *sym;
-  struct block *block = NULL;
+  const struct block *block;
 
   BLPY_REQUIRE_VALID (self, block);
 
@@ -140,8 +140,8 @@ blpy_get_function (PyObject *self, void *closure)
 static PyObject *
 blpy_get_superblock (PyObject *self, void *closure)
 {
-  struct block *block = NULL;
-  struct block *super_block = NULL;
+  const struct block *block;
+  const struct block *super_block;
   block_object *self_obj  = (block_object *) self;
 
   BLPY_REQUIRE_VALID (self, block);
@@ -153,6 +153,114 @@ blpy_get_superblock (PyObject *self, void *closure)
   Py_RETURN_NONE;
 }
 
+/* Return the global block associated to this block.  */
+
+static PyObject *
+blpy_get_global_block (PyObject *self, void *closure)
+{
+  const struct block *block;
+  const struct block *global_block;
+  block_object *self_obj  = (block_object *) self;
+
+  BLPY_REQUIRE_VALID (self, block);
+
+  global_block = block_global_block (block);
+
+  return block_to_block_object (global_block,
+                               self_obj->objfile);
+
+}
+
+/* Return the static block associated to this block.  Return None
+   if we cannot get the static block (this is the global block).  */
+
+static PyObject *
+blpy_get_static_block (PyObject *self, void *closure)
+{
+  const struct block *block;
+  const struct block *static_block;
+  block_object *self_obj  = (block_object *) self;
+
+  BLPY_REQUIRE_VALID (self, block);
+
+  if (BLOCK_SUPERBLOCK (block) == NULL)
+    Py_RETURN_NONE;
+
+  static_block = block_static_block (block);
+
+  return block_to_block_object (static_block, self_obj->objfile);
+}
+
+/* Implementation of gdb.Block.is_global (self) -> Boolean.
+   Returns True if this block object is a global block.  */
+
+static PyObject *
+blpy_is_global (PyObject *self, void *closure)
+{
+  const struct block *block;
+
+  BLPY_REQUIRE_VALID (self, block);
+
+  if (BLOCK_SUPERBLOCK (block))
+    Py_RETURN_FALSE;
+
+  Py_RETURN_TRUE;
+}
+
+/* Implementation of gdb.Block.is_static (self) -> Boolean.
+   Returns True if this block object is a static block.  */
+
+static PyObject *
+blpy_is_static (PyObject *self, void *closure)
+{
+  const struct block *block;
+
+  BLPY_REQUIRE_VALID (self, block);
+
+  if (BLOCK_SUPERBLOCK (block) != NULL
+     && BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+/* Given a string, returns the gdb.Symbol representing that symbol in this
+   block.  If such a symbol does not exist, returns NULL with a Python
+   exception.  */
+
+static PyObject *
+blpy_getitem (PyObject *self, PyObject *key)
+{
+  const struct block *block;
+
+  BLPY_REQUIRE_VALID (self, block);
+
+  gdb::unique_xmalloc_ptr<char> name = python_string_to_host_string (key);
+  if (name == nullptr)
+    return nullptr;
+
+  lookup_name_info lookup_name (name.get(), symbol_name_match_type::FULL);
+
+  /* We use ALL_BLOCK_SYMBOLS_WITH_NAME instead of block_lookup_symbol so
+     that we can look up symbols irrespective of the domain, matching the
+     iterator. It would be confusing if the iterator returns symbols you
+     can't find via getitem.  */
+  struct block_iterator iter;
+  struct symbol *sym = nullptr;
+  ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym)
+    {
+      /* Just stop at the first match */
+      break;
+    }
+
+  if (sym == nullptr)
+    {
+      PyErr_SetObject (PyExc_KeyError, key);
+      return nullptr;
+    }
+  return symbol_to_symbol_object (sym);
+}
+
 static void
 blpy_dealloc (PyObject *obj)
 {
@@ -168,15 +276,16 @@ blpy_dealloc (PyObject *obj)
   if (block->next)
     block->next->prev = block->prev;
   block->block = NULL;
+  Py_TYPE (obj)->tp_free (obj);
 }
 
 /* Given a block, and a block_object that has previously been
    allocated and initialized, populate the block_object with the
    struct block data.  Also, register the block_object life-cycle
-   with the life-cycle of the the object file associated with this
+   with the life-cycle of the object file associated with this
    block, if needed.  */
 static void
-set_block (block_object *obj, struct block *block,
+set_block (block_object *obj, const struct block *block,
           struct objfile *objfile)
 {
   obj->block = block;
@@ -184,7 +293,8 @@ set_block (block_object *obj, struct block *block,
   if (objfile)
     {
       obj->objfile = objfile;
-      obj->next = objfile_data (objfile, blpy_objfile_data_key);
+      obj->next = ((struct blpy_block_object *)
+                  objfile_data (objfile, blpy_objfile_data_key));
       if (obj->next)
        obj->next->prev = obj;
       set_objfile_data (objfile, blpy_objfile_data_key, obj);
@@ -196,7 +306,7 @@ set_block (block_object *obj, struct block *block,
 /* Create a new block object (gdb.Block) that encapsulates the struct
    block object from GDB.  */
 PyObject *
-block_to_block_object (struct block *block, struct objfile *objfile)
+block_to_block_object (const struct block *block, struct objfile *objfile)
 {
   block_object *block_obj;
 
@@ -208,7 +318,7 @@ block_to_block_object (struct block *block, struct objfile *objfile)
 }
 
 /* Return struct block reference that is wrapped by this object.  */
-struct block *
+const struct block *
 block_object_to_block (PyObject *obj)
 {
   if (! PyObject_TypeCheck (obj, &block_object_type))
@@ -240,11 +350,11 @@ blpy_block_syms_iternext (PyObject *self)
 
   if (!iter_obj->initialized_p)
     {
-      sym = dict_iterator_first (iter_obj->dict,  &(iter_obj->iter));
+      sym = block_iterator_first (iter_obj->block,  &(iter_obj->iter));
       iter_obj->initialized_p = 1;
     }
   else
-    sym = dict_iterator_next (&(iter_obj->iter));
+    sym = block_iterator_next (&(iter_obj->iter));
 
   if (sym == NULL)
     {
@@ -261,35 +371,37 @@ blpy_block_syms_dealloc (PyObject *obj)
   block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) obj;
 
   Py_XDECREF (iter_obj->source);
+  Py_TYPE (obj)->tp_free (obj);
 }
 
-/* Return the innermost lexical block containing the specified pc value,
-   or 0 if there is none.  */
-PyObject *
-gdbpy_block_for_pc (PyObject *self, PyObject *args)
+/* Implementation of gdb.Block.is_valid (self) -> Boolean.
+   Returns True if this block object still exists in GDB.  */
+
+static PyObject *
+blpy_is_valid (PyObject *self, PyObject *args)
 {
-  unsigned PY_LONG_LONG pc;
-  struct block *block;
-  struct obj_section *section;
-  struct symtab *symtab;
+  const struct block *block;
 
-  if (!PyArg_ParseTuple (args, "K", &pc))
-    return NULL;
+  block = block_object_to_block (self);
+  if (block == NULL)
+    Py_RETURN_FALSE;
 
-  section = find_pc_mapped_section (pc);
-  symtab = find_pc_sect_symtab (pc, section);
-  if (!symtab || symtab->objfile == NULL)
-    {
-      PyErr_SetString (PyExc_RuntimeError,
-                      _("Cannot locate object file for block."));
-      return NULL;
-    }
+  Py_RETURN_TRUE;
+}
 
-  block = block_for_pc (pc);
-  if (block)
-    return block_to_block_object (block, symtab->objfile);
+/* Implementation of gdb.BlockIterator.is_valid (self) -> Boolean.
+   Returns True if this block iterator object still exists in GDB  */
 
-  Py_RETURN_NONE;
+static PyObject *
+blpy_iter_is_valid (PyObject *self, PyObject *args)
+{
+  block_syms_iterator_object *iter_obj =
+    (block_syms_iterator_object *) self;
+
+  if (iter_obj->source->block == NULL)
+    Py_RETURN_FALSE;
+
+  Py_RETURN_TRUE;
 }
 
 /* This function is called when an objfile is about to be freed.
@@ -300,7 +412,7 @@ gdbpy_block_for_pc (PyObject *self, PyObject *args)
 static void
 del_objfile_blocks (struct objfile *objfile, void *datum)
 {
-  block_object *obj = datum;
+  block_object *obj = (block_object *) datum;
 
   while (obj)
     {
@@ -315,16 +427,16 @@ del_objfile_blocks (struct objfile *objfile, void *datum)
     }
 }
 
-void
+int
 gdbpy_initialize_blocks (void)
 {
   block_object_type.tp_new = PyType_GenericNew;
   if (PyType_Ready (&block_object_type) < 0)
-    return;
+    return -1;
 
   block_syms_iterator_object_type.tp_new = PyType_GenericNew;
   if (PyType_Ready (&block_syms_iterator_object_type) < 0)
-    return;
+    return -1;
 
   /* Register an objfile "free" callback so we can properly
      invalidate blocks when an object file is about to be
@@ -332,29 +444,49 @@ gdbpy_initialize_blocks (void)
   blpy_objfile_data_key
     = register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
 
-  Py_INCREF (&block_object_type);
-  PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type);
+  if (gdb_pymodule_addobject (gdb_module, "Block",
+                             (PyObject *) &block_object_type) < 0)
+    return -1;
 
-  Py_INCREF (&block_syms_iterator_object_type);
-  PyModule_AddObject (gdb_module, "BlockIterator",
-                     (PyObject *) &block_syms_iterator_object_type);
+  return gdb_pymodule_addobject (gdb_module, "BlockIterator",
+                                (PyObject *) &block_syms_iterator_object_type);
 }
 
 \f
 
-static PyGetSetDef block_object_getset[] = {
+static PyMethodDef block_object_methods[] = {
+  { "is_valid", blpy_is_valid, METH_NOARGS,
+    "is_valid () -> Boolean.\n\
+Return true if this block is valid, false if not." },
+  {NULL}  /* Sentinel */
+};
+
+static gdb_PyGetSetDef block_object_getset[] = {
   { "start", blpy_get_start, NULL, "Start address of the block.", NULL },
   { "end", blpy_get_end, NULL, "End address of the block.", NULL },
   { "function", blpy_get_function, NULL,
     "Symbol that names the block, or None.", NULL },
   { "superblock", blpy_get_superblock, NULL,
     "Block containing the block, or None.", NULL },
+  { "global_block", blpy_get_global_block, NULL,
+    "Block containing the global block.", NULL },
+  { "static_block", blpy_get_static_block, NULL,
+    "Block containing the static block.", NULL },
+  { "is_static", blpy_is_static, NULL,
+    "Whether this block is a static block.", NULL },
+  { "is_global", blpy_is_global, NULL,
+    "Whether this block is a global block.", NULL },
   { NULL }  /* Sentinel */
 };
 
+static PyMappingMethods block_object_as_mapping = {
+  NULL,
+  blpy_getitem,
+  NULL
+};
+
 PyTypeObject block_object_type = {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.Block",                   /*tp_name*/
   sizeof (block_object),         /*tp_basicsize*/
   0,                             /*tp_itemsize*/
@@ -366,7 +498,7 @@ PyTypeObject block_object_type = {
   0,                             /*tp_repr*/
   0,                             /*tp_as_number*/
   0,                             /*tp_as_sequence*/
-  0,                             /*tp_as_mapping*/
+  &block_object_as_mapping,      /*tp_as_mapping*/
   0,                             /*tp_hash */
   0,                             /*tp_call*/
   0,                             /*tp_str*/
@@ -381,14 +513,20 @@ PyTypeObject block_object_type = {
   0,                             /* tp_weaklistoffset */
   blpy_iter,                     /* tp_iter */
   0,                             /* tp_iternext */
-  0,                             /* tp_methods */
+  block_object_methods,                  /* tp_methods */
   0,                             /* tp_members */
   block_object_getset            /* tp_getset */
 };
 
-static PyTypeObject block_syms_iterator_object_type = {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+static PyMethodDef block_iterator_object_methods[] = {
+  { "is_valid", blpy_iter_is_valid, METH_NOARGS,
+    "is_valid () -> Boolean.\n\
+Return true if this block iterator is valid, false if not." },
+  {NULL}  /* Sentinel */
+};
+
+PyTypeObject block_syms_iterator_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.BlockIterator",           /*tp_name*/
   sizeof (block_syms_iterator_object),       /*tp_basicsize*/
   0,                             /*tp_itemsize*/
@@ -415,5 +553,5 @@ static PyTypeObject block_syms_iterator_object_type = {
   0,                             /*tp_weaklistoffset */
   blpy_block_syms_iter,           /*tp_iter */
   blpy_block_syms_iternext,      /*tp_iternext */
-  0                              /*tp_methods */
+  block_iterator_object_methods   /*tp_methods */
 };
This page took 0.035992 seconds and 4 git commands to generate.