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