Home | History | Annotate | Line # | Download | only in guile
      1  1.1  christos /* Scheme interface to blocks.
      2  1.1  christos 
      3  1.9  christos    Copyright (C) 2008-2024 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GDB.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19  1.1  christos 
     20  1.1  christos /* See README file in this directory for implementation notes, coding
     21  1.1  christos    conventions, et.al.  */
     22  1.1  christos 
     23  1.1  christos #include "block.h"
     24  1.1  christos #include "dictionary.h"
     25  1.1  christos #include "objfiles.h"
     26  1.1  christos #include "source.h"
     27  1.1  christos #include "symtab.h"
     28  1.1  christos #include "guile-internal.h"
     29  1.1  christos 
     30  1.1  christos /* A smob describing a gdb block.  */
     31  1.1  christos 
     32  1.8  christos struct block_smob
     33  1.1  christos {
     34  1.1  christos   /* This always appears first.
     35  1.1  christos      We want blocks to be eq?-able.  And we need to be able to invalidate
     36  1.1  christos      blocks when the associated objfile is deleted.  */
     37  1.1  christos   eqable_gdb_smob base;
     38  1.1  christos 
     39  1.1  christos   /* The GDB block structure that represents a frame's code block.  */
     40  1.1  christos   const struct block *block;
     41  1.1  christos 
     42  1.1  christos   /* The backing object file.  There is no direct relationship in GDB
     43  1.1  christos      between a block and an object file.  When a block is created also
     44  1.1  christos      store a pointer to the object file for later use.  */
     45  1.1  christos   struct objfile *objfile;
     46  1.8  christos };
     47  1.1  christos 
     48  1.1  christos /* To iterate over block symbols from Scheme we need to store
     49  1.1  christos    struct block_iterator somewhere.  This is stored in the "progress" field
     50  1.1  christos    of <gdb:iterator>.  We store the block object in iterator_smob.object,
     51  1.1  christos    so we don't store it here.
     52  1.1  christos 
     53  1.1  christos    Remember: While iterating over block symbols, you must continually check
     54  1.1  christos    whether the block is still valid.  */
     55  1.1  christos 
     56  1.8  christos struct block_syms_progress_smob
     57  1.1  christos {
     58  1.1  christos   /* This always appears first.  */
     59  1.1  christos   gdb_smob base;
     60  1.1  christos 
     61  1.1  christos   /* The iterator for that block.  */
     62  1.1  christos   struct block_iterator iter;
     63  1.1  christos 
     64  1.1  christos   /* Has the iterator been initialized flag.  */
     65  1.1  christos   int initialized_p;
     66  1.8  christos };
     67  1.1  christos 
     68  1.1  christos static const char block_smob_name[] = "gdb:block";
     69  1.1  christos static const char block_syms_progress_smob_name[] = "gdb:block-symbols-iterator";
     70  1.1  christos 
     71  1.1  christos /* The tag Guile knows the block smobs by.  */
     72  1.1  christos static scm_t_bits block_smob_tag;
     73  1.1  christos static scm_t_bits block_syms_progress_smob_tag;
     74  1.1  christos 
     75  1.1  christos /* The "next!" block syms iterator method.  */
     76  1.1  christos static SCM bkscm_next_symbol_x_proc;
     77  1.1  christos 
     78  1.8  christos /* This is called when an objfile is about to be freed.
     79  1.8  christos    Invalidate the block as further actions on the block would result
     80  1.8  christos    in bad data.  All access to b_smob->block should be gated by
     81  1.8  christos    checks to ensure the block is (still) valid.  */
     82  1.8  christos struct bkscm_deleter
     83  1.8  christos {
     84  1.8  christos   /* Helper function for bkscm_del_objfile_blocks to mark the block
     85  1.8  christos      as invalid.  */
     86  1.8  christos 
     87  1.8  christos   static int
     88  1.8  christos   bkscm_mark_block_invalid (void **slot, void *info)
     89  1.8  christos   {
     90  1.8  christos     block_smob *b_smob = (block_smob *) *slot;
     91  1.8  christos 
     92  1.8  christos     b_smob->block = NULL;
     93  1.8  christos     b_smob->objfile = NULL;
     94  1.8  christos     return 1;
     95  1.8  christos   }
     96  1.8  christos 
     97  1.8  christos   void operator() (htab_t htab)
     98  1.8  christos   {
     99  1.8  christos     gdb_assert (htab != nullptr);
    100  1.8  christos     htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL);
    101  1.8  christos     htab_delete (htab);
    102  1.8  christos   }
    103  1.8  christos };
    104  1.8  christos 
    105  1.8  christos static const registry<objfile>::key<htab, bkscm_deleter>
    106  1.8  christos      bkscm_objfile_data_key;
    107  1.1  christos 
    108  1.1  christos /* Administrivia for block smobs.  */
    110  1.1  christos 
    111  1.1  christos /* Helper function to hash a block_smob.  */
    112  1.1  christos 
    113  1.1  christos static hashval_t
    114  1.1  christos bkscm_hash_block_smob (const void *p)
    115  1.4  christos {
    116  1.1  christos   const block_smob *b_smob = (const block_smob *) p;
    117  1.1  christos 
    118  1.1  christos   return htab_hash_pointer (b_smob->block);
    119  1.1  christos }
    120  1.1  christos 
    121  1.1  christos /* Helper function to compute equality of block_smobs.  */
    122  1.1  christos 
    123  1.1  christos static int
    124  1.1  christos bkscm_eq_block_smob (const void *ap, const void *bp)
    125  1.4  christos {
    126  1.4  christos   const block_smob *a = (const block_smob *) ap;
    127  1.1  christos   const block_smob *b = (const block_smob *) bp;
    128  1.1  christos 
    129  1.1  christos   return (a->block == b->block
    130  1.1  christos 	  && a->block != NULL);
    131  1.1  christos }
    132  1.1  christos 
    133  1.1  christos /* Return the struct block pointer -> SCM mapping table.
    134  1.1  christos    It is created if necessary.  */
    135  1.1  christos 
    136  1.1  christos static htab_t
    137  1.1  christos bkscm_objfile_block_map (struct objfile *objfile)
    138  1.8  christos {
    139  1.1  christos   htab_t htab = bkscm_objfile_data_key.get (objfile);
    140  1.1  christos 
    141  1.1  christos   if (htab == NULL)
    142  1.1  christos     {
    143  1.1  christos       htab = gdbscm_create_eqable_gsmob_ptr_map (bkscm_hash_block_smob,
    144  1.8  christos 						 bkscm_eq_block_smob);
    145  1.1  christos       bkscm_objfile_data_key.set (objfile, htab);
    146  1.1  christos     }
    147  1.1  christos 
    148  1.1  christos   return htab;
    149  1.1  christos }
    150  1.1  christos 
    151  1.1  christos /* The smob "free" function for <gdb:block>.  */
    152  1.1  christos 
    153  1.1  christos static size_t
    154  1.1  christos bkscm_free_block_smob (SCM self)
    155  1.1  christos {
    156  1.1  christos   block_smob *b_smob = (block_smob *) SCM_SMOB_DATA (self);
    157  1.1  christos 
    158  1.1  christos   if (b_smob->block != NULL)
    159  1.1  christos     {
    160  1.1  christos       htab_t htab = bkscm_objfile_block_map (b_smob->objfile);
    161  1.1  christos 
    162  1.1  christos       gdbscm_clear_eqable_gsmob_ptr_slot (htab, &b_smob->base);
    163  1.1  christos     }
    164  1.1  christos 
    165  1.1  christos   /* Not necessary, done to catch bugs.  */
    166  1.1  christos   b_smob->block = NULL;
    167  1.1  christos   b_smob->objfile = NULL;
    168  1.1  christos 
    169  1.1  christos   return 0;
    170  1.1  christos }
    171  1.1  christos 
    172  1.1  christos /* The smob "print" function for <gdb:block>.  */
    173  1.1  christos 
    174  1.1  christos static int
    175  1.1  christos bkscm_print_block_smob (SCM self, SCM port, scm_print_state *pstate)
    176  1.1  christos {
    177  1.1  christos   block_smob *b_smob = (block_smob *) SCM_SMOB_DATA (self);
    178  1.1  christos   const struct block *b = b_smob->block;
    179  1.1  christos 
    180  1.1  christos   gdbscm_printf (port, "#<%s", block_smob_name);
    181  1.8  christos 
    182  1.1  christos   if (b->superblock () == NULL)
    183  1.8  christos     gdbscm_printf (port, " global");
    184  1.1  christos   else if (b->superblock ()->superblock () == NULL)
    185  1.1  christos     gdbscm_printf (port, " static");
    186  1.8  christos 
    187  1.8  christos   if (b->function () != NULL)
    188  1.1  christos     gdbscm_printf (port, " %s", b->function ()->print_name ());
    189  1.1  christos 
    190  1.8  christos   gdbscm_printf (port, " %s-%s",
    191  1.1  christos 		 hex_string (b->start ()), hex_string (b->end ()));
    192  1.1  christos 
    193  1.1  christos   scm_puts (">", port);
    194  1.1  christos 
    195  1.1  christos   scm_remember_upto_here_1 (self);
    196  1.1  christos 
    197  1.1  christos   /* Non-zero means success.  */
    198  1.1  christos   return 1;
    199  1.1  christos }
    200  1.1  christos 
    201  1.1  christos /* Low level routine to create a <gdb:block> object.  */
    202  1.1  christos 
    203  1.1  christos static SCM
    204  1.1  christos bkscm_make_block_smob (void)
    205  1.1  christos {
    206  1.1  christos   block_smob *b_smob = (block_smob *)
    207  1.1  christos     scm_gc_malloc (sizeof (block_smob), block_smob_name);
    208  1.1  christos   SCM b_scm;
    209  1.1  christos 
    210  1.1  christos   b_smob->block = NULL;
    211  1.1  christos   b_smob->objfile = NULL;
    212  1.1  christos   b_scm = scm_new_smob (block_smob_tag, (scm_t_bits) b_smob);
    213  1.1  christos   gdbscm_init_eqable_gsmob (&b_smob->base, b_scm);
    214  1.1  christos 
    215  1.1  christos   return b_scm;
    216  1.1  christos }
    217  1.1  christos 
    218  1.1  christos /* Returns non-zero if SCM is a <gdb:block> object.  */
    219  1.1  christos 
    220  1.1  christos static int
    221  1.1  christos bkscm_is_block (SCM scm)
    222  1.1  christos {
    223  1.1  christos   return SCM_SMOB_PREDICATE (block_smob_tag, scm);
    224  1.1  christos }
    225  1.1  christos 
    226  1.1  christos /* (block? scm) -> boolean */
    227  1.1  christos 
    228  1.1  christos static SCM
    229  1.1  christos gdbscm_block_p (SCM scm)
    230  1.1  christos {
    231  1.1  christos   return scm_from_bool (bkscm_is_block (scm));
    232  1.1  christos }
    233  1.1  christos 
    234  1.1  christos /* Return the existing object that encapsulates BLOCK, or create a new
    235  1.1  christos    <gdb:block> object.  */
    236  1.1  christos 
    237  1.1  christos SCM
    238  1.1  christos bkscm_scm_from_block (const struct block *block, struct objfile *objfile)
    239  1.1  christos {
    240  1.1  christos   htab_t htab;
    241  1.1  christos   eqable_gdb_smob **slot;
    242  1.1  christos   block_smob *b_smob, b_smob_for_lookup;
    243  1.1  christos   SCM b_scm;
    244  1.1  christos 
    245  1.1  christos   /* If we've already created a gsmob for this block, return it.
    246  1.1  christos      This makes blocks eq?-able.  */
    247  1.1  christos   htab = bkscm_objfile_block_map (objfile);
    248  1.1  christos   b_smob_for_lookup.block = block;
    249  1.1  christos   slot = gdbscm_find_eqable_gsmob_ptr_slot (htab, &b_smob_for_lookup.base);
    250  1.1  christos   if (*slot != NULL)
    251  1.1  christos     return (*slot)->containing_scm;
    252  1.1  christos 
    253  1.1  christos   b_scm = bkscm_make_block_smob ();
    254  1.1  christos   b_smob = (block_smob *) SCM_SMOB_DATA (b_scm);
    255  1.1  christos   b_smob->block = block;
    256  1.1  christos   b_smob->objfile = objfile;
    257  1.1  christos   gdbscm_fill_eqable_gsmob_ptr_slot (slot, &b_smob->base);
    258  1.1  christos 
    259  1.1  christos   return b_scm;
    260  1.1  christos }
    261  1.1  christos 
    262  1.1  christos /* Returns the <gdb:block> object in SELF.
    263  1.1  christos    Throws an exception if SELF is not a <gdb:block> object.  */
    264  1.1  christos 
    265  1.1  christos static SCM
    266  1.1  christos bkscm_get_block_arg_unsafe (SCM self, int arg_pos, const char *func_name)
    267  1.1  christos {
    268  1.1  christos   SCM_ASSERT_TYPE (bkscm_is_block (self), self, arg_pos, func_name,
    269  1.1  christos 		   block_smob_name);
    270  1.1  christos 
    271  1.1  christos   return self;
    272  1.1  christos }
    273  1.1  christos 
    274  1.1  christos /* Returns a pointer to the block smob of SELF.
    275  1.1  christos    Throws an exception if SELF is not a <gdb:block> object.  */
    276  1.1  christos 
    277  1.1  christos static block_smob *
    278  1.1  christos bkscm_get_block_smob_arg_unsafe (SCM self, int arg_pos, const char *func_name)
    279  1.1  christos {
    280  1.1  christos   SCM b_scm = bkscm_get_block_arg_unsafe (self, arg_pos, func_name);
    281  1.1  christos   block_smob *b_smob = (block_smob *) SCM_SMOB_DATA (b_scm);
    282  1.1  christos 
    283  1.1  christos   return b_smob;
    284  1.1  christos }
    285  1.1  christos 
    286  1.1  christos /* Returns non-zero if block B_SMOB is valid.  */
    287  1.1  christos 
    288  1.1  christos static int
    289  1.1  christos bkscm_is_valid (block_smob *b_smob)
    290  1.1  christos {
    291  1.1  christos   return b_smob->block != NULL;
    292  1.1  christos }
    293  1.1  christos 
    294  1.1  christos /* Returns the block smob in SELF, verifying it's valid.
    295  1.1  christos    Throws an exception if SELF is not a <gdb:block> object or is invalid.  */
    296  1.1  christos 
    297  1.1  christos static block_smob *
    298  1.1  christos bkscm_get_valid_block_smob_arg_unsafe (SCM self, int arg_pos,
    299  1.1  christos 				       const char *func_name)
    300  1.1  christos {
    301  1.1  christos   block_smob *b_smob
    302  1.1  christos     = bkscm_get_block_smob_arg_unsafe (self, arg_pos, func_name);
    303  1.1  christos 
    304  1.1  christos   if (!bkscm_is_valid (b_smob))
    305  1.1  christos     {
    306  1.1  christos       gdbscm_invalid_object_error (func_name, arg_pos, self,
    307  1.1  christos 				   _("<gdb:block>"));
    308  1.1  christos     }
    309  1.1  christos 
    310  1.1  christos   return b_smob;
    311  1.1  christos }
    312  1.1  christos 
    313  1.1  christos /* Returns the block smob contained in SCM or NULL if SCM is not a
    314  1.1  christos    <gdb:block> object.
    315  1.1  christos    If there is an error a <gdb:exception> object is stored in *EXCP.  */
    316  1.1  christos 
    317  1.1  christos static block_smob *
    318  1.1  christos bkscm_get_valid_block (SCM scm, int arg_pos, const char *func_name, SCM *excp)
    319  1.1  christos {
    320  1.1  christos   block_smob *b_smob;
    321  1.1  christos 
    322  1.1  christos   if (!bkscm_is_block (scm))
    323  1.1  christos     {
    324  1.1  christos       *excp = gdbscm_make_type_error (func_name, arg_pos, scm,
    325  1.1  christos 				      block_smob_name);
    326  1.1  christos       return NULL;
    327  1.1  christos     }
    328  1.1  christos 
    329  1.1  christos   b_smob = (block_smob *) SCM_SMOB_DATA (scm);
    330  1.1  christos   if (!bkscm_is_valid (b_smob))
    331  1.1  christos     {
    332  1.1  christos       *excp = gdbscm_make_invalid_object_error (func_name, arg_pos, scm,
    333  1.1  christos 						_("<gdb:block>"));
    334  1.1  christos       return NULL;
    335  1.1  christos     }
    336  1.1  christos 
    337  1.1  christos   return b_smob;
    338  1.1  christos }
    339  1.1  christos 
    340  1.1  christos /* Returns the struct block that is wrapped by BLOCK_SCM.
    341  1.1  christos    If BLOCK_SCM is not a block, or is an invalid block, then NULL is returned
    342  1.1  christos    and a <gdb:exception> object is stored in *EXCP.  */
    343  1.1  christos 
    344  1.1  christos const struct block *
    345  1.1  christos bkscm_scm_to_block (SCM block_scm, int arg_pos, const char *func_name,
    346  1.1  christos 		    SCM *excp)
    347  1.1  christos {
    348  1.1  christos   block_smob *b_smob;
    349  1.1  christos 
    350  1.1  christos   b_smob = bkscm_get_valid_block (block_scm, arg_pos, func_name, excp);
    351  1.1  christos 
    352  1.1  christos   if (b_smob != NULL)
    353  1.1  christos     return b_smob->block;
    354  1.1  christos   return NULL;
    355  1.1  christos }
    356  1.1  christos 
    357  1.1  christos 
    358  1.1  christos /* Block methods.  */
    360  1.1  christos 
    361  1.1  christos /* (block-valid? <gdb:block>) -> boolean
    362  1.1  christos    Returns #t if SELF still exists in GDB.  */
    363  1.1  christos 
    364  1.1  christos static SCM
    365  1.1  christos gdbscm_block_valid_p (SCM self)
    366  1.1  christos {
    367  1.1  christos   block_smob *b_smob
    368  1.1  christos     = bkscm_get_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    369  1.1  christos 
    370  1.1  christos   return scm_from_bool (bkscm_is_valid (b_smob));
    371  1.1  christos }
    372  1.1  christos 
    373  1.1  christos /* (block-start <gdb:block>) -> address */
    374  1.1  christos 
    375  1.1  christos static SCM
    376  1.1  christos gdbscm_block_start (SCM self)
    377  1.1  christos {
    378  1.1  christos   block_smob *b_smob
    379  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    380  1.8  christos   const struct block *block = b_smob->block;
    381  1.1  christos 
    382  1.1  christos   return gdbscm_scm_from_ulongest (block->start ());
    383  1.1  christos }
    384  1.1  christos 
    385  1.1  christos /* (block-end <gdb:block>) -> address */
    386  1.1  christos 
    387  1.1  christos static SCM
    388  1.1  christos gdbscm_block_end (SCM self)
    389  1.1  christos {
    390  1.1  christos   block_smob *b_smob
    391  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    392  1.8  christos   const struct block *block = b_smob->block;
    393  1.1  christos 
    394  1.1  christos   return gdbscm_scm_from_ulongest (block->end ());
    395  1.1  christos }
    396  1.1  christos 
    397  1.1  christos /* (block-function <gdb:block>) -> <gdb:symbol> */
    398  1.1  christos 
    399  1.1  christos static SCM
    400  1.1  christos gdbscm_block_function (SCM self)
    401  1.1  christos {
    402  1.1  christos   block_smob *b_smob
    403  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    404  1.1  christos   const struct block *block = b_smob->block;
    405  1.8  christos   struct symbol *sym;
    406  1.1  christos 
    407  1.1  christos   sym = block->function ();
    408  1.1  christos 
    409  1.1  christos   if (sym != NULL)
    410  1.1  christos     return syscm_scm_from_symbol (sym);
    411  1.1  christos   return SCM_BOOL_F;
    412  1.1  christos }
    413  1.1  christos 
    414  1.1  christos /* (block-superblock <gdb:block>) -> <gdb:block> */
    415  1.1  christos 
    416  1.1  christos static SCM
    417  1.1  christos gdbscm_block_superblock (SCM self)
    418  1.1  christos {
    419  1.1  christos   block_smob *b_smob
    420  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    421  1.1  christos   const struct block *block = b_smob->block;
    422  1.8  christos   const struct block *super_block;
    423  1.1  christos 
    424  1.1  christos   super_block = block->superblock ();
    425  1.1  christos 
    426  1.1  christos   if (super_block)
    427  1.1  christos     return bkscm_scm_from_block (super_block, b_smob->objfile);
    428  1.1  christos   return SCM_BOOL_F;
    429  1.1  christos }
    430  1.1  christos 
    431  1.1  christos /* (block-global-block <gdb:block>) -> <gdb:block>
    432  1.1  christos    Returns the global block associated to this block.  */
    433  1.1  christos 
    434  1.1  christos static SCM
    435  1.1  christos gdbscm_block_global_block (SCM self)
    436  1.1  christos {
    437  1.1  christos   block_smob *b_smob
    438  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    439  1.1  christos   const struct block *block = b_smob->block;
    440  1.9  christos   const struct block *global_block;
    441  1.1  christos 
    442  1.1  christos   global_block = block->global_block ();
    443  1.1  christos 
    444  1.1  christos   return bkscm_scm_from_block (global_block, b_smob->objfile);
    445  1.1  christos }
    446  1.1  christos 
    447  1.1  christos /* (block-static-block <gdb:block>) -> <gdb:block>
    448  1.1  christos    Returns the static block associated to this block.
    449  1.1  christos    Returns #f if we cannot get the static block (this is the global block).  */
    450  1.1  christos 
    451  1.1  christos static SCM
    452  1.1  christos gdbscm_block_static_block (SCM self)
    453  1.1  christos {
    454  1.1  christos   block_smob *b_smob
    455  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    456  1.1  christos   const struct block *block = b_smob->block;
    457  1.8  christos   const struct block *static_block;
    458  1.1  christos 
    459  1.1  christos   if (block->superblock () == NULL)
    460  1.9  christos     return SCM_BOOL_F;
    461  1.1  christos 
    462  1.1  christos   static_block = block->static_block ();
    463  1.1  christos 
    464  1.1  christos   return bkscm_scm_from_block (static_block, b_smob->objfile);
    465  1.1  christos }
    466  1.1  christos 
    467  1.1  christos /* (block-global? <gdb:block>) -> boolean
    468  1.1  christos    Returns #t if this block object is a global block.  */
    469  1.1  christos 
    470  1.1  christos static SCM
    471  1.1  christos gdbscm_block_global_p (SCM self)
    472  1.1  christos {
    473  1.1  christos   block_smob *b_smob
    474  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    475  1.8  christos   const struct block *block = b_smob->block;
    476  1.1  christos 
    477  1.1  christos   return scm_from_bool (block->superblock () == NULL);
    478  1.1  christos }
    479  1.1  christos 
    480  1.1  christos /* (block-static? <gdb:block>) -> boolean
    481  1.1  christos    Returns #t if this block object is a static block.  */
    482  1.1  christos 
    483  1.1  christos static SCM
    484  1.1  christos gdbscm_block_static_p (SCM self)
    485  1.1  christos {
    486  1.1  christos   block_smob *b_smob
    487  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    488  1.8  christos   const struct block *block = b_smob->block;
    489  1.8  christos 
    490  1.1  christos   if (block->superblock () != NULL
    491  1.1  christos       && block->superblock ()->superblock () == NULL)
    492  1.1  christos     return SCM_BOOL_T;
    493  1.1  christos   return SCM_BOOL_F;
    494  1.1  christos }
    495  1.1  christos 
    496  1.1  christos /* (block-symbols <gdb:block>) -> list of <gdb:symbol objects
    497  1.1  christos    Returns a list of symbols of the block.  */
    498  1.1  christos 
    499  1.1  christos static SCM
    500  1.1  christos gdbscm_block_symbols (SCM self)
    501  1.1  christos {
    502  1.1  christos   block_smob *b_smob
    503  1.1  christos     = bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    504  1.1  christos   const struct block *block = b_smob->block;
    505  1.1  christos   SCM result;
    506  1.1  christos 
    507  1.9  christos   result = SCM_EOL;
    508  1.1  christos 
    509  1.1  christos   for (struct symbol *sym : block_iterator_range (block))
    510  1.1  christos     {
    511  1.1  christos       SCM s_scm = syscm_scm_from_symbol (sym);
    512  1.1  christos 
    513  1.1  christos       result = scm_cons (s_scm, result);
    514  1.1  christos     }
    515  1.1  christos 
    516  1.1  christos   return scm_reverse_x (result, SCM_EOL);
    517  1.1  christos }
    518  1.1  christos 
    519  1.1  christos /* The <gdb:block-symbols-iterator> object,
    521  1.1  christos    for iterating over all symbols in a block.  */
    522  1.1  christos 
    523  1.1  christos /* The smob "print" function for <gdb:block-symbols-iterator>.  */
    524  1.1  christos 
    525  1.1  christos static int
    526  1.1  christos bkscm_print_block_syms_progress_smob (SCM self, SCM port,
    527  1.1  christos 				      scm_print_state *pstate)
    528  1.1  christos {
    529  1.1  christos   block_syms_progress_smob *i_smob
    530  1.1  christos     = (block_syms_progress_smob *) SCM_SMOB_DATA (self);
    531  1.1  christos 
    532  1.1  christos   gdbscm_printf (port, "#<%s", block_syms_progress_smob_name);
    533  1.1  christos 
    534  1.1  christos   if (i_smob->initialized_p)
    535  1.1  christos     {
    536  1.1  christos       switch (i_smob->iter.which)
    537  1.1  christos 	{
    538  1.1  christos 	case GLOBAL_BLOCK:
    539  1.1  christos 	case STATIC_BLOCK:
    540  1.1  christos 	  {
    541  1.1  christos 	    struct compunit_symtab *cust;
    542  1.1  christos 
    543  1.1  christos 	    gdbscm_printf (port, " %s",
    544  1.1  christos 			   i_smob->iter.which == GLOBAL_BLOCK
    545  1.1  christos 			   ? "global" : "static");
    546  1.1  christos 	    if (i_smob->iter.idx != -1)
    547  1.1  christos 	      gdbscm_printf (port, " @%d", i_smob->iter.idx);
    548  1.1  christos 	    cust = (i_smob->iter.idx == -1
    549  1.1  christos 		    ? i_smob->iter.d.compunit_symtab
    550  1.8  christos 		    : i_smob->iter.d.compunit_symtab->includes[i_smob->iter.idx]);
    551  1.1  christos 	    gdbscm_printf (port, " %s",
    552  1.1  christos 			   symtab_to_filename_for_display
    553  1.1  christos 			     (cust->primary_filetab ()));
    554  1.1  christos 	    break;
    555  1.1  christos 	  }
    556  1.1  christos 	case FIRST_LOCAL_BLOCK:
    557  1.1  christos 	  gdbscm_printf (port, " single block");
    558  1.1  christos 	  break;
    559  1.1  christos 	}
    560  1.1  christos     }
    561  1.1  christos   else
    562  1.1  christos     gdbscm_printf (port, " !initialized");
    563  1.1  christos 
    564  1.1  christos   scm_puts (">", port);
    565  1.1  christos 
    566  1.1  christos   scm_remember_upto_here_1 (self);
    567  1.1  christos 
    568  1.1  christos   /* Non-zero means success.  */
    569  1.1  christos   return 1;
    570  1.1  christos }
    571  1.1  christos 
    572  1.1  christos /* Low level routine to create a <gdb:block-symbols-progress> object.  */
    573  1.1  christos 
    574  1.1  christos static SCM
    575  1.1  christos bkscm_make_block_syms_progress_smob (void)
    576  1.1  christos {
    577  1.1  christos   block_syms_progress_smob *i_smob = (block_syms_progress_smob *)
    578  1.1  christos     scm_gc_malloc (sizeof (block_syms_progress_smob),
    579  1.1  christos 		   block_syms_progress_smob_name);
    580  1.1  christos   SCM smob;
    581  1.1  christos 
    582  1.1  christos   memset (&i_smob->iter, 0, sizeof (i_smob->iter));
    583  1.1  christos   i_smob->initialized_p = 0;
    584  1.1  christos   smob = scm_new_smob (block_syms_progress_smob_tag, (scm_t_bits) i_smob);
    585  1.1  christos   gdbscm_init_gsmob (&i_smob->base);
    586  1.1  christos 
    587  1.1  christos   return smob;
    588  1.1  christos }
    589  1.1  christos 
    590  1.1  christos /* Returns non-zero if SCM is a <gdb:block-symbols-progress> object.  */
    591  1.1  christos 
    592  1.1  christos static int
    593  1.1  christos bkscm_is_block_syms_progress (SCM scm)
    594  1.1  christos {
    595  1.1  christos   return SCM_SMOB_PREDICATE (block_syms_progress_smob_tag, scm);
    596  1.1  christos }
    597  1.1  christos 
    598  1.1  christos /* (block-symbols-progress? scm) -> boolean */
    599  1.1  christos 
    600  1.1  christos static SCM
    601  1.1  christos bkscm_block_syms_progress_p (SCM scm)
    602  1.1  christos {
    603  1.1  christos   return scm_from_bool (bkscm_is_block_syms_progress (scm));
    604  1.1  christos }
    605  1.1  christos 
    606  1.1  christos /* (make-block-symbols-iterator <gdb:block>) -> <gdb:iterator>
    607  1.1  christos    Return a <gdb:iterator> object for iterating over the symbols of SELF.  */
    608  1.1  christos 
    609  1.6  christos static SCM
    610  1.6  christos gdbscm_make_block_syms_iter (SCM self)
    611  1.1  christos {
    612  1.1  christos   /* Call for side effects.  */
    613  1.1  christos   bkscm_get_valid_block_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    614  1.1  christos   SCM progress, iter;
    615  1.1  christos 
    616  1.1  christos   progress = bkscm_make_block_syms_progress_smob ();
    617  1.1  christos 
    618  1.1  christos   iter = gdbscm_make_iterator (self, progress, bkscm_next_symbol_x_proc);
    619  1.1  christos 
    620  1.1  christos   return iter;
    621  1.1  christos }
    622  1.1  christos 
    623  1.1  christos /* Returns the next symbol in the iteration through the block's dictionary,
    624  1.1  christos    or (end-of-iteration).
    625  1.1  christos    This is the iterator_smob.next_x method.  */
    626  1.1  christos 
    627  1.1  christos static SCM
    628  1.1  christos gdbscm_block_next_symbol_x (SCM self)
    629  1.1  christos {
    630  1.1  christos   SCM progress, iter_scm, block_scm;
    631  1.1  christos   iterator_smob *iter_smob;
    632  1.1  christos   block_smob *b_smob;
    633  1.1  christos   const struct block *block;
    634  1.1  christos   block_syms_progress_smob *p_smob;
    635  1.1  christos   struct symbol *sym;
    636  1.1  christos 
    637  1.1  christos   iter_scm = itscm_get_iterator_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    638  1.1  christos   iter_smob = (iterator_smob *) SCM_SMOB_DATA (iter_scm);
    639  1.1  christos 
    640  1.1  christos   block_scm = itscm_iterator_smob_object (iter_smob);
    641  1.1  christos   b_smob = bkscm_get_valid_block_smob_arg_unsafe (block_scm,
    642  1.1  christos 						  SCM_ARG1, FUNC_NAME);
    643  1.1  christos   block = b_smob->block;
    644  1.1  christos 
    645  1.1  christos   progress = itscm_iterator_smob_progress (iter_smob);
    646  1.1  christos 
    647  1.1  christos   SCM_ASSERT_TYPE (bkscm_is_block_syms_progress (progress),
    648  1.1  christos 		   progress, SCM_ARG1, FUNC_NAME,
    649  1.1  christos 		   block_syms_progress_smob_name);
    650  1.1  christos   p_smob = (block_syms_progress_smob *) SCM_SMOB_DATA (progress);
    651  1.1  christos 
    652  1.1  christos   if (!p_smob->initialized_p)
    653  1.1  christos     {
    654  1.1  christos       sym = block_iterator_first (block, &p_smob->iter);
    655  1.1  christos       p_smob->initialized_p = 1;
    656  1.1  christos     }
    657  1.1  christos   else
    658  1.1  christos     sym = block_iterator_next (&p_smob->iter);
    659  1.1  christos 
    660  1.1  christos   if (sym == NULL)
    661  1.1  christos     return gdbscm_end_of_iteration ();
    662  1.1  christos 
    663  1.1  christos   return syscm_scm_from_symbol (sym);
    664  1.1  christos }
    665  1.1  christos 
    666  1.1  christos /* (lookup-block address) -> <gdb:block>
    668  1.1  christos    Returns the innermost lexical block containing the specified pc value,
    669  1.1  christos    or #f if there is none.  */
    670  1.1  christos 
    671  1.1  christos static SCM
    672  1.1  christos gdbscm_lookup_block (SCM pc_scm)
    673  1.1  christos {
    674  1.1  christos   CORE_ADDR pc;
    675  1.1  christos   const struct block *block = NULL;
    676  1.7  christos   struct compunit_symtab *cust = NULL;
    677  1.7  christos 
    678  1.1  christos   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "U", pc_scm, &pc);
    679  1.1  christos 
    680  1.1  christos   gdbscm_gdb_exception exc {};
    681  1.8  christos   try
    682  1.1  christos     {
    683  1.1  christos       cust = find_pc_compunit_symtab (pc);
    684  1.7  christos 
    685  1.3  christos       if (cust != NULL && cust->objfile () != NULL)
    686  1.7  christos 	block = block_for_pc (pc);
    687  1.3  christos     }
    688  1.1  christos   catch (const gdb_exception &except)
    689  1.7  christos     {
    690  1.8  christos       exc = unpack (except);
    691  1.1  christos     }
    692  1.1  christos 
    693  1.1  christos   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
    694  1.1  christos   if (cust == NULL || cust->objfile () == NULL)
    695  1.1  christos     {
    696  1.1  christos       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, pc_scm,
    697  1.8  christos 				 _("cannot locate object file for block"));
    698  1.1  christos     }
    699  1.1  christos 
    700  1.1  christos   if (block != NULL)
    701  1.1  christos     return bkscm_scm_from_block (block, cust->objfile ());
    702  1.1  christos   return SCM_BOOL_F;
    703  1.1  christos }
    704  1.1  christos 
    705  1.4  christos /* Initialize the Scheme block support.  */
    707  1.1  christos 
    708  1.1  christos static const scheme_function block_functions[] =
    709  1.4  christos {
    710  1.1  christos   { "block?", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_p),
    711  1.1  christos     "\
    712  1.1  christos Return #t if the object is a <gdb:block> object." },
    713  1.1  christos 
    714  1.4  christos   { "block-valid?", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_valid_p),
    715  1.1  christos     "\
    716  1.1  christos Return #t if the block is valid.\n\
    717  1.1  christos A block becomes invalid when its objfile is freed." },
    718  1.4  christos 
    719  1.1  christos   { "block-start", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_start),
    720  1.1  christos     "\
    721  1.1  christos Return the start address of the block." },
    722  1.4  christos 
    723  1.1  christos   { "block-end", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_end),
    724  1.1  christos     "\
    725  1.1  christos Return the end address of the block." },
    726  1.1  christos 
    727  1.4  christos   { "block-function", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_function),
    728  1.1  christos     "\
    729  1.1  christos Return the gdb:symbol object of the function containing the block\n\
    730  1.1  christos or #f if the block does not live in any function." },
    731  1.4  christos 
    732  1.1  christos   { "block-superblock", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_superblock),
    733  1.1  christos     "\
    734  1.1  christos Return the superblock (parent block) of the block." },
    735  1.4  christos 
    736  1.1  christos   { "block-global-block", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_global_block),
    737  1.1  christos     "\
    738  1.1  christos Return the global block of the block." },
    739  1.4  christos 
    740  1.1  christos   { "block-static-block", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_static_block),
    741  1.1  christos     "\
    742  1.1  christos Return the static block of the block." },
    743  1.4  christos 
    744  1.1  christos   { "block-global?", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_global_p),
    745  1.1  christos     "\
    746  1.1  christos Return #t if block is a global block." },
    747  1.4  christos 
    748  1.1  christos   { "block-static?", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_static_p),
    749  1.1  christos     "\
    750  1.1  christos Return #t if block is a static block." },
    751  1.4  christos 
    752  1.4  christos   { "block-symbols", 1, 0, 0, as_a_scm_t_subr (gdbscm_block_symbols),
    753  1.1  christos     "\
    754  1.1  christos Return a list of all symbols (as <gdb:symbol> objects) in the block." },
    755  1.1  christos 
    756  1.4  christos   { "make-block-symbols-iterator", 1, 0, 0,
    757  1.4  christos     as_a_scm_t_subr (gdbscm_make_block_syms_iter),
    758  1.1  christos     "\
    759  1.1  christos Return a <gdb:iterator> object for iterating over all symbols in the block." },
    760  1.1  christos 
    761  1.4  christos   { "block-symbols-progress?", 1, 0, 0,
    762  1.1  christos     as_a_scm_t_subr (bkscm_block_syms_progress_p),
    763  1.1  christos     "\
    764  1.1  christos Return #t if the object is a <gdb:block-symbols-progress> object." },
    765  1.1  christos 
    766  1.1  christos   { "lookup-block", 1, 0, 0, as_a_scm_t_subr (gdbscm_lookup_block),
    767  1.1  christos     "\
    768  1.1  christos Return the innermost GDB block containing the address or #f if none found.\n\
    769  1.1  christos \n\
    770  1.1  christos   Arguments:\n\
    771  1.1  christos     address: the address to lookup" },
    772  1.1  christos 
    773  1.1  christos   END_FUNCTIONS
    774  1.1  christos };
    775  1.1  christos 
    776  1.1  christos void
    777  1.1  christos gdbscm_initialize_blocks (void)
    778  1.1  christos {
    779  1.1  christos   block_smob_tag
    780  1.1  christos     = gdbscm_make_smob_type (block_smob_name, sizeof (block_smob));
    781  1.1  christos   scm_set_smob_free (block_smob_tag, bkscm_free_block_smob);
    782  1.1  christos   scm_set_smob_print (block_smob_tag, bkscm_print_block_smob);
    783  1.1  christos 
    784  1.1  christos   block_syms_progress_smob_tag
    785  1.1  christos     = gdbscm_make_smob_type (block_syms_progress_smob_name,
    786  1.1  christos 			     sizeof (block_syms_progress_smob));
    787  1.1  christos   scm_set_smob_print (block_syms_progress_smob_tag,
    788  1.1  christos 		      bkscm_print_block_syms_progress_smob);
    789  1.1  christos 
    790  1.4  christos   gdbscm_define_functions (block_functions, 1);
    791  1.1  christos 
    792  1.1  christos   /* This function is "private".  */
    793  1.1  christos   bkscm_next_symbol_x_proc
    794  1.1  christos     = scm_c_define_gsubr ("%block-next-symbol!", 1, 0, 0,
    795  1.1  christos 			  as_a_scm_t_subr (gdbscm_block_next_symbol_x));
    796                  scm_set_procedure_property_x (bkscm_next_symbol_x_proc,
    797                				gdbscm_documentation_symbol,
    798                				gdbscm_scm_from_c_string ("\
    799                Internal function to assist the block symbols iterator."));
    800                }
    801