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