Home | History | Annotate | Line # | Download | only in guile
      1  1.1  christos /* Guile interface to program spaces.
      2  1.1  christos 
      3  1.9  christos    Copyright (C) 2010-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 #include "charset.h"
     21  1.1  christos #include "progspace.h"
     22  1.1  christos #include "objfiles.h"
     23  1.1  christos #include "language.h"
     24  1.1  christos #include "arch-utils.h"
     25  1.1  christos #include "guile-internal.h"
     26  1.1  christos 
     27  1.1  christos /* NOTE: Python exports the name "Progspace", so we export "progspace".
     28  1.1  christos    Internally we shorten that to "pspace".  */
     29  1.1  christos 
     30  1.8  christos /* The <gdb:progspace> smob.  */
     31  1.1  christos 
     32  1.8  christos struct pspace_smob
     33  1.1  christos {
     34  1.1  christos   /* This always appears first.  */
     35  1.1  christos   gdb_smob base;
     36  1.1  christos 
     37  1.1  christos   /* The corresponding pspace.  */
     38  1.1  christos   struct program_space *pspace;
     39  1.1  christos 
     40  1.1  christos   /* The pretty-printer list of functions.  */
     41  1.1  christos   SCM pretty_printers;
     42  1.1  christos 
     43  1.1  christos   /* The <gdb:progspace> object we are contained in, needed to
     44  1.1  christos      protect/unprotect the object since a reference to it comes from
     45  1.1  christos      non-gc-managed space (the progspace).  */
     46  1.1  christos   SCM containing_scm;
     47  1.1  christos };
     48  1.1  christos 
     49  1.1  christos static const char pspace_smob_name[] = "gdb:progspace";
     50  1.1  christos 
     51  1.1  christos /* The tag Guile knows the pspace smob by.  */
     52  1.1  christos static scm_t_bits pspace_smob_tag;
     53  1.1  christos 
     54  1.8  christos /* Progspace registry cleanup handler for when a progspace is deleted.  */
     55  1.8  christos struct psscm_deleter
     56  1.8  christos {
     57  1.8  christos   void operator() (pspace_smob *p_smob)
     58  1.8  christos   {
     59  1.8  christos     p_smob->pspace = NULL;
     60  1.8  christos     scm_gc_unprotect_object (p_smob->containing_scm);
     61  1.8  christos   }
     62  1.8  christos };
     63  1.8  christos 
     64  1.8  christos static const registry<program_space>::key<pspace_smob, psscm_deleter>
     65  1.8  christos      psscm_pspace_data_key;
     66  1.1  christos 
     67  1.1  christos /* Return the list of pretty-printers registered with P_SMOB.  */
     68  1.1  christos 
     69  1.1  christos SCM
     70  1.1  christos psscm_pspace_smob_pretty_printers (const pspace_smob *p_smob)
     71  1.1  christos {
     72  1.1  christos   return p_smob->pretty_printers;
     73  1.1  christos }
     74  1.1  christos 
     75  1.1  christos /* Administrivia for progspace smobs.  */
     77  1.1  christos 
     78  1.1  christos /* The smob "print" function for <gdb:progspace>.  */
     79  1.1  christos 
     80  1.1  christos static int
     81  1.1  christos psscm_print_pspace_smob (SCM self, SCM port, scm_print_state *pstate)
     82  1.1  christos {
     83  1.1  christos   pspace_smob *p_smob = (pspace_smob *) SCM_SMOB_DATA (self);
     84  1.1  christos 
     85  1.1  christos   gdbscm_printf (port, "#<%s ", pspace_smob_name);
     86  1.1  christos   if (p_smob->pspace != NULL)
     87  1.1  christos     {
     88  1.1  christos       struct objfile *objfile = p_smob->pspace->symfile_object_file;
     89  1.1  christos 
     90  1.1  christos       gdbscm_printf (port, "%s",
     91  1.1  christos 		     objfile != NULL
     92  1.1  christos 		     ? objfile_name (objfile)
     93  1.1  christos 		     : "{no symfile}");
     94  1.1  christos     }
     95  1.1  christos   else
     96  1.1  christos     scm_puts ("{invalid}", port);
     97  1.1  christos   scm_puts (">", port);
     98  1.1  christos 
     99  1.1  christos   scm_remember_upto_here_1 (self);
    100  1.1  christos 
    101  1.1  christos   /* Non-zero means success.  */
    102  1.1  christos   return 1;
    103  1.1  christos }
    104  1.1  christos 
    105  1.1  christos /* Low level routine to create a <gdb:progspace> object.
    106  1.1  christos    It's empty in the sense that a progspace still needs to be associated
    107  1.1  christos    with it.  */
    108  1.1  christos 
    109  1.1  christos static SCM
    110  1.1  christos psscm_make_pspace_smob (void)
    111  1.1  christos {
    112  1.1  christos   pspace_smob *p_smob = (pspace_smob *)
    113  1.1  christos     scm_gc_malloc (sizeof (pspace_smob), pspace_smob_name);
    114  1.1  christos   SCM p_scm;
    115  1.1  christos 
    116  1.1  christos   p_smob->pspace = NULL;
    117  1.1  christos   p_smob->pretty_printers = SCM_EOL;
    118  1.1  christos   p_scm = scm_new_smob (pspace_smob_tag, (scm_t_bits) p_smob);
    119  1.1  christos   p_smob->containing_scm = p_scm;
    120  1.1  christos   gdbscm_init_gsmob (&p_smob->base);
    121  1.1  christos 
    122  1.1  christos   return p_scm;
    123  1.1  christos }
    124  1.1  christos 
    125  1.1  christos /* Return non-zero if SCM is a <gdb:progspace> object.  */
    126  1.1  christos 
    127  1.1  christos static int
    128  1.1  christos psscm_is_pspace (SCM scm)
    129  1.1  christos {
    130  1.1  christos   return SCM_SMOB_PREDICATE (pspace_smob_tag, scm);
    131  1.1  christos }
    132  1.1  christos 
    133  1.1  christos /* (progspace? object) -> boolean */
    134  1.1  christos 
    135  1.1  christos static SCM
    136  1.1  christos gdbscm_progspace_p (SCM scm)
    137  1.1  christos {
    138  1.1  christos   return scm_from_bool (psscm_is_pspace (scm));
    139  1.1  christos }
    140  1.1  christos 
    141  1.1  christos /* Return a pointer to the progspace_smob that encapsulates PSPACE,
    142  1.1  christos    creating one if necessary.
    143  1.1  christos    The result is cached so that we have only one copy per objfile.  */
    144  1.1  christos 
    145  1.1  christos pspace_smob *
    146  1.1  christos psscm_pspace_smob_from_pspace (struct program_space *pspace)
    147  1.1  christos {
    148  1.1  christos   pspace_smob *p_smob;
    149  1.8  christos 
    150  1.1  christos   p_smob = psscm_pspace_data_key.get (pspace);
    151  1.1  christos   if (p_smob == NULL)
    152  1.1  christos     {
    153  1.1  christos       SCM p_scm = psscm_make_pspace_smob ();
    154  1.1  christos 
    155  1.1  christos       p_smob = (pspace_smob *) SCM_SMOB_DATA (p_scm);
    156  1.1  christos       p_smob->pspace = pspace;
    157  1.8  christos 
    158  1.1  christos       psscm_pspace_data_key.set (pspace, p_smob);
    159  1.1  christos       scm_gc_protect_object (p_smob->containing_scm);
    160  1.1  christos     }
    161  1.1  christos 
    162  1.1  christos   return p_smob;
    163  1.1  christos }
    164  1.1  christos 
    165  1.1  christos /* Return the <gdb:progspace> object that encapsulates PSPACE.  */
    166  1.1  christos 
    167  1.1  christos SCM
    168  1.1  christos psscm_scm_from_pspace (struct program_space *pspace)
    169  1.1  christos {
    170  1.1  christos   pspace_smob *p_smob = psscm_pspace_smob_from_pspace (pspace);
    171  1.1  christos 
    172  1.1  christos   return p_smob->containing_scm;
    173  1.1  christos }
    174  1.1  christos 
    175  1.1  christos /* Returns the <gdb:progspace> object in SELF.
    176  1.1  christos    Throws an exception if SELF is not a <gdb:progspace> object.  */
    177  1.1  christos 
    178  1.1  christos static SCM
    179  1.1  christos psscm_get_pspace_arg_unsafe (SCM self, int arg_pos, const char *func_name)
    180  1.1  christos {
    181  1.1  christos   SCM_ASSERT_TYPE (psscm_is_pspace (self), self, arg_pos, func_name,
    182  1.1  christos 		   pspace_smob_name);
    183  1.1  christos 
    184  1.1  christos   return self;
    185  1.1  christos }
    186  1.1  christos 
    187  1.1  christos /* Returns a pointer to the pspace smob of SELF.
    188  1.1  christos    Throws an exception if SELF is not a <gdb:progspace> object.  */
    189  1.1  christos 
    190  1.1  christos static pspace_smob *
    191  1.1  christos psscm_get_pspace_smob_arg_unsafe (SCM self, int arg_pos,
    192  1.1  christos 				  const char *func_name)
    193  1.1  christos {
    194  1.1  christos   SCM p_scm = psscm_get_pspace_arg_unsafe (self, arg_pos, func_name);
    195  1.1  christos   pspace_smob *p_smob = (pspace_smob *) SCM_SMOB_DATA (p_scm);
    196  1.1  christos 
    197  1.1  christos   return p_smob;
    198  1.1  christos }
    199  1.1  christos 
    200  1.1  christos /* Return non-zero if pspace P_SMOB is valid.  */
    201  1.1  christos 
    202  1.1  christos static int
    203  1.1  christos psscm_is_valid (pspace_smob *p_smob)
    204  1.1  christos {
    205  1.1  christos   return p_smob->pspace != NULL;
    206  1.1  christos }
    207  1.1  christos 
    208  1.1  christos /* Return the pspace smob in SELF, verifying it's valid.
    209  1.1  christos    Throws an exception if SELF is not a <gdb:progspace> object or is
    210  1.1  christos    invalid.  */
    211  1.1  christos 
    212  1.1  christos static pspace_smob *
    213  1.1  christos psscm_get_valid_pspace_smob_arg_unsafe (SCM self, int arg_pos,
    214  1.1  christos 					const char *func_name)
    215  1.1  christos {
    216  1.1  christos   pspace_smob *p_smob
    217  1.1  christos     = psscm_get_pspace_smob_arg_unsafe (self, arg_pos, func_name);
    218  1.1  christos 
    219  1.1  christos   if (!psscm_is_valid (p_smob))
    220  1.1  christos     {
    221  1.1  christos       gdbscm_invalid_object_error (func_name, arg_pos, self,
    222  1.1  christos 				   _("<gdb:progspace>"));
    223  1.1  christos     }
    224  1.1  christos 
    225  1.1  christos   return p_smob;
    226  1.1  christos }
    227  1.1  christos 
    228  1.1  christos /* Program space methods.  */
    230  1.1  christos 
    231  1.1  christos /* (progspace-valid? <gdb:progspace>) -> boolean
    232  1.1  christos    Returns #t if this program space still exists in GDB.  */
    233  1.1  christos 
    234  1.1  christos static SCM
    235  1.1  christos gdbscm_progspace_valid_p (SCM self)
    236  1.1  christos {
    237  1.1  christos   pspace_smob *p_smob
    238  1.1  christos     = psscm_get_pspace_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    239  1.1  christos 
    240  1.1  christos   return scm_from_bool (p_smob->pspace != NULL);
    241  1.1  christos }
    242  1.1  christos 
    243  1.1  christos /* (progspace-filename <gdb:progspace>) -> string
    244  1.1  christos    Returns the name of the main symfile associated with the progspace,
    245  1.1  christos    or #f if there isn't one.
    246  1.1  christos    Throw's an exception if the underlying pspace is invalid.  */
    247  1.1  christos 
    248  1.1  christos static SCM
    249  1.1  christos gdbscm_progspace_filename (SCM self)
    250  1.1  christos {
    251  1.1  christos   pspace_smob *p_smob
    252  1.1  christos     = psscm_get_valid_pspace_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    253  1.1  christos   struct objfile *objfile = p_smob->pspace->symfile_object_file;
    254  1.1  christos 
    255  1.1  christos   if (objfile != NULL)
    256  1.1  christos     return gdbscm_scm_from_c_string (objfile_name (objfile));
    257  1.1  christos   return SCM_BOOL_F;
    258  1.1  christos }
    259  1.1  christos 
    260  1.1  christos /* (progspace-objfiles <gdb:progspace>) -> list
    261  1.1  christos    Return the list of objfiles in the progspace.
    262  1.1  christos    Objfiles that are separate debug objfiles are *not* included in the result,
    263  1.1  christos    only the "original/real" one appears in the result.
    264  1.1  christos    The order of appearance of objfiles in the result is arbitrary.
    265  1.1  christos    Throw's an exception if the underlying pspace is invalid.
    266  1.1  christos 
    267  1.1  christos    Some apps can have 1000s of shared libraries.  Seriously.
    268  1.1  christos    A future extension here could be to provide, e.g., a regexp to select
    269  1.1  christos    just the ones the caller is interested in (rather than building the list
    270  1.1  christos    and then selecting the desired ones).  Another alternative is passing a
    271  1.1  christos    predicate, then the filter criteria can be more general.  */
    272  1.1  christos 
    273  1.1  christos static SCM
    274  1.1  christos gdbscm_progspace_objfiles (SCM self)
    275  1.1  christos {
    276  1.1  christos   pspace_smob *p_smob
    277  1.1  christos     = psscm_get_valid_pspace_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    278  1.1  christos   SCM result;
    279  1.1  christos 
    280  1.6  christos   result = SCM_EOL;
    281  1.6  christos 
    282  1.6  christos   for (objfile *objfile : p_smob->pspace->objfiles ())
    283  1.6  christos     {
    284  1.6  christos       if (objfile->separate_debug_objfile_backlink == NULL)
    285  1.1  christos 	{
    286  1.6  christos 	  SCM item = ofscm_scm_from_objfile (objfile);
    287  1.6  christos 
    288  1.6  christos 	  result = scm_cons (item, result);
    289  1.1  christos 	}
    290  1.1  christos     }
    291  1.1  christos 
    292  1.1  christos   /* We don't really have to return the list in the same order as recorded
    293  1.1  christos      internally, but for consistency we do.  We still advertise that one
    294  1.1  christos      cannot assume anything about the order.  */
    295  1.1  christos   return scm_reverse_x (result, SCM_EOL);
    296  1.1  christos }
    297  1.1  christos 
    298  1.1  christos /* (progspace-pretty-printers <gdb:progspace>) -> list
    299  1.1  christos    Returns the list of pretty-printers for this program space.  */
    300  1.1  christos 
    301  1.1  christos static SCM
    302  1.1  christos gdbscm_progspace_pretty_printers (SCM self)
    303  1.1  christos {
    304  1.1  christos   pspace_smob *p_smob
    305  1.1  christos     = psscm_get_pspace_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    306  1.1  christos 
    307  1.1  christos   return p_smob->pretty_printers;
    308  1.1  christos }
    309  1.1  christos 
    310  1.1  christos /* (set-progspace-pretty-printers! <gdb:progspace> list) -> unspecified
    311  1.1  christos    Set the pretty-printers for this program space.  */
    312  1.1  christos 
    313  1.1  christos static SCM
    314  1.1  christos gdbscm_set_progspace_pretty_printers_x (SCM self, SCM printers)
    315  1.1  christos {
    316  1.1  christos   pspace_smob *p_smob
    317  1.1  christos     = psscm_get_pspace_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    318  1.1  christos 
    319  1.1  christos   SCM_ASSERT_TYPE (gdbscm_is_true (scm_list_p (printers)), printers,
    320  1.1  christos 		   SCM_ARG2, FUNC_NAME, _("list"));
    321  1.1  christos 
    322  1.1  christos   p_smob->pretty_printers = printers;
    323  1.1  christos 
    324  1.1  christos   return SCM_UNSPECIFIED;
    325  1.1  christos }
    326  1.1  christos 
    327  1.1  christos /* (current-progspace) -> <gdb:progspace>
    328  1.1  christos    Return the current program space.  There always is one.  */
    329  1.1  christos 
    330  1.1  christos static SCM
    331  1.1  christos gdbscm_current_progspace (void)
    332  1.1  christos {
    333  1.1  christos   SCM result;
    334  1.1  christos 
    335  1.1  christos   result = psscm_scm_from_pspace (current_program_space);
    336  1.1  christos 
    337  1.1  christos   return result;
    338  1.1  christos }
    339  1.1  christos 
    340  1.1  christos /* (progspaces) -> list
    341  1.1  christos    Return a list of all progspaces.  */
    342  1.1  christos 
    343  1.1  christos static SCM
    344  1.1  christos gdbscm_progspaces (void)
    345  1.1  christos {
    346  1.1  christos   SCM result;
    347  1.1  christos 
    348  1.7  christos   result = SCM_EOL;
    349  1.7  christos 
    350  1.7  christos   for (struct program_space *ps : program_spaces)
    351  1.1  christos     {
    352  1.7  christos       SCM item = psscm_scm_from_pspace (ps);
    353  1.7  christos 
    354  1.1  christos       result = scm_cons (item, result);
    355  1.1  christos     }
    356  1.1  christos 
    357  1.1  christos   return scm_reverse_x (result, SCM_EOL);
    358  1.1  christos }
    359  1.1  christos 
    360  1.1  christos /* Initialize the Scheme program space support.  */
    362  1.4  christos 
    363  1.1  christos static const scheme_function pspace_functions[] =
    364  1.1  christos {
    365  1.1  christos   { "progspace?", 1, 0, 0, as_a_scm_t_subr (gdbscm_progspace_p),
    366  1.4  christos     "\
    367  1.1  christos Return #t if the object is a <gdb:objfile> object." },
    368  1.1  christos 
    369  1.1  christos   { "progspace-valid?", 1, 0, 0, as_a_scm_t_subr (gdbscm_progspace_valid_p),
    370  1.4  christos     "\
    371  1.1  christos Return #t if the progspace is valid (hasn't been deleted from gdb)." },
    372  1.1  christos 
    373  1.1  christos   { "progspace-filename", 1, 0, 0, as_a_scm_t_subr (gdbscm_progspace_filename),
    374  1.4  christos     "\
    375  1.1  christos Return the name of the main symbol file of the progspace." },
    376  1.1  christos 
    377  1.1  christos   { "progspace-objfiles", 1, 0, 0, as_a_scm_t_subr (gdbscm_progspace_objfiles),
    378  1.1  christos     "\
    379  1.1  christos Return the list of objfiles associated with the progspace.\n\
    380  1.4  christos Objfiles that are separate debug objfiles are not included in the result.\n\
    381  1.4  christos The order of appearance of objfiles in the result is arbitrary." },
    382  1.1  christos 
    383  1.1  christos   { "progspace-pretty-printers", 1, 0, 0,
    384  1.1  christos     as_a_scm_t_subr (gdbscm_progspace_pretty_printers),
    385  1.1  christos     "\
    386  1.4  christos Return a list of pretty-printers of the progspace." },
    387  1.1  christos 
    388  1.1  christos   { "set-progspace-pretty-printers!", 2, 0, 0,
    389  1.1  christos     as_a_scm_t_subr (gdbscm_set_progspace_pretty_printers_x),
    390  1.4  christos     "\
    391  1.1  christos Set the list of pretty-printers of the progspace." },
    392  1.1  christos 
    393  1.1  christos   { "current-progspace", 0, 0, 0, as_a_scm_t_subr (gdbscm_current_progspace),
    394  1.4  christos     "\
    395  1.1  christos Return the current program space if there is one or #f if there isn't one." },
    396  1.1  christos 
    397  1.1  christos   { "progspaces", 0, 0, 0, as_a_scm_t_subr (gdbscm_progspaces),
    398  1.1  christos     "\
    399  1.1  christos Return a list of all program spaces." },
    400  1.1  christos 
    401  1.1  christos   END_FUNCTIONS
    402  1.1  christos };
    403  1.1  christos 
    404  1.1  christos void
    405  1.1  christos gdbscm_initialize_pspaces (void)
    406  1.1  christos {
    407  1.1  christos   pspace_smob_tag
    408  1.1  christos     = gdbscm_make_smob_type (pspace_smob_name, sizeof (pspace_smob));
    409  1.1  christos   scm_set_smob_print (pspace_smob_tag, psscm_print_pspace_smob);
    410                
    411                  gdbscm_define_functions (pspace_functions, 1);
    412                }
    413