Home | History | Annotate | Download | only in ltrace
      1 /*
      2  * This file is part of ltrace.
      3  * Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU General Public License as
      7  * published by the Free Software Foundation; either version 2 of the
      8  * License, or (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     18  * 02110-1301 USA
     19  */
     20 
     21 #ifndef _PROTOTYPE_H_
     22 #define _PROTOTYPE_H_
     23 
     24 #include <stdbool.h>
     25 
     26 #include "forward.h"
     27 #include "dict.h"
     28 #include "vect.h"
     29 
     30 /* Function prototype.  */
     31 struct prototype {
     32 	/* Vector of struct param.  */
     33 	struct vect params;
     34 
     35 	struct arg_type_info *return_info;
     36 	int own_return_info : 1;
     37 };
     38 
     39 /* Initialize a prototype PROTO.  The name will be NAME, and the
     40  * corresponding string will be owned and freed on destroy if
     41  * OWN_NAME.  */
     42 void prototype_init(struct prototype *proto);
     43 
     44 /* Destroy PROTO (but don't free the memory block pointed-to by
     45  * PROTO).  */
     46 void prototype_destroy(struct prototype *proto);
     47 
     48 /* Add new parameter PARAM to PROTO.  The structure contents are
     49  * copied and PARAM pointer itself is not owned by PROTO.  */
     50 int prototype_push_param(struct prototype *proto, struct param *param);
     51 
     52 /* Return number of parameters of prototype.  */
     53 size_t prototype_num_params(struct prototype *proto);
     54 
     55 /* Destroy N-th parameter from PROTO.  N shall be smaller than the
     56  * number of parameters.  */
     57 void prototype_destroy_nth_param(struct prototype *proto, size_t n);
     58 
     59 /* Get N-th parameter of PROTO.  N shall be smaller than the number of
     60  * parameters.  */
     61 struct param *prototype_get_nth_param(struct prototype *proto, size_t n);
     62 
     63 /* Iterate through the parameters of PROTO.  See callback.h for notes
     64  * on iteration interfaces.  */
     65 struct param *prototype_each_param
     66 	(struct prototype *proto, struct param *start_after,
     67 	 enum callback_status (*cb)(struct prototype *, struct param *, void *),
     68 	 void *data);
     69 
     70 /* For storing type aliases.  */
     71 struct named_type {
     72 	struct arg_type_info *info;
     73 	int forward : 1;
     74 	int own_type : 1;
     75 };
     76 
     77 /* Initialize a named type INFO, which, if OWN_TYPE, is destroyed when
     78  * named_type_destroy is called.  */
     79 void named_type_init(struct named_type *named,
     80 		     struct arg_type_info *info, int own_type);
     81 
     82 void named_type_destroy(struct named_type *named);
     83 
     84 /* One prototype library.  */
     85 struct protolib {
     86 	/* Other libraries to look through if the definition is not
     87 	 * found here.  Note that due to the way imports are stored,
     88 	 * there is no way to distinguish where exactly (at which
     89 	 * place of the config file) the import was made.  */
     90 	struct vect imports;
     91 
     92 	/* Dictionary of name->struct prototype.  */
     93 	struct dict prototypes;
     94 
     95 	/* Dictionary of name->struct named_type.  */
     96 	struct dict named_types;
     97 
     98 	/* Reference count.  */
     99 	unsigned refs;
    100 };
    101 
    102 /* Initialize PLIB.  */
    103 void protolib_init(struct protolib *plib);
    104 
    105 /* Destroy PLIB.  */
    106 void protolib_destroy(struct protolib *plib);
    107 
    108 /* Push IMPORT to PLIB.  Returns 0 on success or a negative value on
    109  * failure.  In particular, -2 is returned if mutual import is
    110  * detected.  */
    111 int protolib_add_import(struct protolib *plib, struct protolib *import);
    112 
    113 /* Add a prototype PROTO to PLIB.  Returns 0 on success or a negative
    114  * value on failure.  NAME is owned and released on PLIB destruction
    115  * if OWN_NAME.  */
    116 int protolib_add_prototype(struct protolib *plib,
    117 			   const char *name, int own_name,
    118 			   struct prototype *proto);
    119 
    120 /* Add a named type NAMED to PLIB.  Returns 0 on success or a negative
    121  * value on failure.  NAME is owned and released on PLIB destruction
    122  * if OWN_NAME.  NAMED _pointer_ is copied to PLIB.  */
    123 int protolib_add_named_type(struct protolib *plib,
    124 			    const char *name, int own_name,
    125 			    struct named_type *named);
    126 
    127 /* Lookup prototype named NAME in PLIB.  If none is found and IMPORTS
    128  * is true, look recursively in each of the imports.  Returns the
    129  * corresponding prototype, or NULL if none was found.  */
    130 struct prototype *protolib_lookup_prototype(struct protolib *plib,
    131 					    const char *name, bool imports);
    132 
    133 /* Add a named type NAMED to PLIB.  Returns 0 on success or a negative
    134  * value on failure.  */
    135 int protolib_add_type(struct protolib *plib, struct named_type *named);
    136 
    137 /* Lookup type named NAME in PLIB.  If none is found and IMPORTS is
    138  * true, look recursively in each of the imports.  Returns the
    139  * corresponding type, or NULL if none was found.  */
    140 struct named_type *protolib_lookup_type(struct protolib *plib,
    141 					const char *name, bool imports);
    142 
    143 /* A cache of prototype libraries.  Can load prototype libraries on
    144  * demand.
    145  *
    146  * XXX ltrace should open one config per ABI, which maps long, int,
    147  * etc. to uint32_t etc.  It would also map char to either of
    148  * {u,}int8_t.  Other protolibs would have this as implicit import.
    149  * That would mean that the cache needs ABI tagging--each ABI should
    150  * have a separate prototype cache, because the types will potentially
    151  * differ between the ABI's.  protolib cache would then naturally be
    152  * stored in the ABI object, when this is introduced.  */
    153 struct protolib_cache {
    154 	/* Dictionary of filename->protolib*.  */
    155 	struct dict protolibs;
    156 
    157 	/* Fake module for implicit imports.  This is populated by all
    158 	 * files coming from -F.  When -F is empty, it also contains
    159 	 * either $HOME/.ltrace.conf, or /etc/ltrace.conf (whichever
    160 	 * comes first).  */
    161 	struct protolib imports;
    162 
    163 	/* For tracking uses of cache during cache's own
    164 	 * initialization.  */
    165 	int bootstrap : 1;
    166 };
    167 
    168 /* Initialize CACHE.  Returns 0 on success or a negative value on
    169  * failure.  */
    170 int protolib_cache_init(struct protolib_cache *cache,
    171 			struct protolib *import);
    172 
    173 /* Destroy CACHE.  */
    174 void protolib_cache_destroy(struct protolib_cache *cache);
    175 
    176 /* Get protolib corresponding to KEY from CACHE.  KEY would typically
    177  * be the soname of a library for which a protolib should be obtained.
    178  * If none has been loaded yet, load a new protolib, cache and return
    179  * it.  Returns NULL for failures.
    180  *
    181  * Protolibs are loaded from a config directory.  If -F contains
    182  * directory names, those are checked first.  Next, os_get_config_dirs
    183  * callback is used to get a list of directories to look into.  In the
    184  * first round, if ALLOW_PRIVATE, ltrace looks in user's private
    185  * directories.  If the config file wasn't found, the second round is
    186  * made through system directories.  In each directory, ltrace looks
    187  * and reads the file named KEY.conf.
    188  *
    189  * If the config file still wasn't found, an empty (but non-NULL)
    190  * protolib is provided instead.  That is augmented with the following
    191  * imports:
    192  *
    193  * - Legacy typedefs
    194  * - The IMPORT argument passed to protolib_cache_init, if non-NULL
    195  * - $HOME/.ltrace.conf if available
    196  * - @sysconfdir@/ltrace.conf if available
    197  * - Any configure _files_ passed in -F
    198  *
    199  * This function returns either the loaded protolib, or NULL when
    200  * there was an error.  */
    201 struct protolib *protolib_cache_load(struct protolib_cache *cache,
    202 				     const char *key, int own_key,
    203 				     bool allow_private);
    204 
    205 /* This is similar to protolib_cache_load, except that if a protolib
    206  * is not found NULL is returned instead of a default module.
    207  *
    208  * It returns 0 for success and a negative value for failure, and the
    209  * actual return value is passed via *RET.*/
    210 int protolib_cache_maybe_load(struct protolib_cache *cache,
    211 			      const char *key, int own_key,
    212 			      bool allow_private,
    213 			      struct protolib **ret);
    214 
    215 /* This is similar to protolib_cache_load, but instead of looking for
    216  * the file to load in directories, the filename is given.  */
    217 struct protolib *protolib_cache_file(struct protolib_cache *cache,
    218 				     const char *filename, int own_filename);
    219 
    220 /* This caches a default module.  This is what protolib_cache_load
    221  * calls if it fails to find the actual protolib.  Returns default
    222  * protolib or NULL if there was an error.  */
    223 struct protolib *protolib_cache_default(struct protolib_cache *cache,
    224 					const char *key, int own_key);
    225 
    226 /* This is similar to protolib_cache_file, but the library to cache is
    227  * given in argument.  Returns 0 on success or a negative value on
    228  * failure.  PLIB is thereafter owned by CACHE.  */
    229 int protolib_cache_protolib(struct protolib_cache *cache,
    230 			    const char *filename, int own_filename,
    231 			    struct protolib *plib);
    232 
    233 /* Single global prototype cache.
    234  *
    235  * XXX Eventually each ABI should have its own cache.  The idea is
    236  * that there's one per-ABI config file that all others use for
    237  * elementary typedefs (long, char, size_t).  Ltrace then only deals
    238  * in fixed-width integral types (and pointers etc.).  */
    239 extern struct protolib_cache g_protocache;
    240 
    241 void init_global_config(void);
    242 
    243 #endif /* _PROTOTYPE_H_ */
    244