Blame prototype.h

Packit 0021fb
/*
Packit 0021fb
 * This file is part of ltrace.
Packit 0021fb
 * Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
Packit 0021fb
 *
Packit 0021fb
 * This program is free software; you can redistribute it and/or
Packit 0021fb
 * modify it under the terms of the GNU General Public License as
Packit 0021fb
 * published by the Free Software Foundation; either version 2 of the
Packit 0021fb
 * License, or (at your option) any later version.
Packit 0021fb
 *
Packit 0021fb
 * This program is distributed in the hope that it will be useful, but
Packit 0021fb
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0021fb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 0021fb
 * General Public License for more details.
Packit 0021fb
 *
Packit 0021fb
 * You should have received a copy of the GNU General Public License
Packit 0021fb
 * along with this program; if not, write to the Free Software
Packit 0021fb
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
Packit 0021fb
 * 02110-1301 USA
Packit 0021fb
 */
Packit 0021fb
Packit 0021fb
#ifndef _PROTOTYPE_H_
Packit 0021fb
#define _PROTOTYPE_H_
Packit 0021fb
Packit 0021fb
#include <stdbool.h>
Packit 0021fb
Packit 0021fb
#include "forward.h"
Packit 0021fb
#include "dict.h"
Packit 0021fb
#include "vect.h"
Packit 0021fb
Packit 0021fb
/* Function prototype.  */
Packit 0021fb
struct prototype {
Packit 0021fb
	/* Vector of struct param.  */
Packit 0021fb
	struct vect params;
Packit 0021fb
Packit 0021fb
	struct arg_type_info *return_info;
Packit 0021fb
	int own_return_info : 1;
Packit 0021fb
};
Packit 0021fb
Packit 0021fb
/* Initialize a prototype PROTO.  The name will be NAME, and the
Packit 0021fb
 * corresponding string will be owned and freed on destroy if
Packit 0021fb
 * OWN_NAME.  */
Packit 0021fb
void prototype_init(struct prototype *proto);
Packit 0021fb
Packit 0021fb
/* Destroy PROTO (but don't free the memory block pointed-to by
Packit 0021fb
 * PROTO).  */
Packit 0021fb
void prototype_destroy(struct prototype *proto);
Packit 0021fb
Packit 0021fb
/* Add new parameter PARAM to PROTO.  The structure contents are
Packit 0021fb
 * copied and PARAM pointer itself is not owned by PROTO.  */
Packit 0021fb
int prototype_push_param(struct prototype *proto, struct param *param);
Packit 0021fb
Packit 0021fb
/* Return number of parameters of prototype.  */
Packit 0021fb
size_t prototype_num_params(struct prototype *proto);
Packit 0021fb
Packit 0021fb
/* Destroy N-th parameter from PROTO.  N shall be smaller than the
Packit 0021fb
 * number of parameters.  */
Packit 0021fb
void prototype_destroy_nth_param(struct prototype *proto, size_t n);
Packit 0021fb
Packit 0021fb
/* Get N-th parameter of PROTO.  N shall be smaller than the number of
Packit 0021fb
 * parameters.  */
Packit 0021fb
struct param *prototype_get_nth_param(struct prototype *proto, size_t n);
Packit 0021fb
Packit 0021fb
/* Iterate through the parameters of PROTO.  See callback.h for notes
Packit 0021fb
 * on iteration interfaces.  */
Packit 0021fb
struct param *prototype_each_param
Packit 0021fb
	(struct prototype *proto, struct param *start_after,
Packit 0021fb
	 enum callback_status (*cb)(struct prototype *, struct param *, void *),
Packit 0021fb
	 void *data);
Packit 0021fb
Packit 0021fb
/* For storing type aliases.  */
Packit 0021fb
struct named_type {
Packit 0021fb
	struct arg_type_info *info;
Packit 0021fb
	int forward : 1;
Packit 0021fb
	int own_type : 1;
Packit 0021fb
};
Packit 0021fb
Packit 0021fb
/* Initialize a named type INFO, which, if OWN_TYPE, is destroyed when
Packit 0021fb
 * named_type_destroy is called.  */
Packit 0021fb
void named_type_init(struct named_type *named,
Packit 0021fb
		     struct arg_type_info *info, int own_type);
Packit 0021fb
Packit 0021fb
void named_type_destroy(struct named_type *named);
Packit 0021fb
Packit 0021fb
/* One prototype library.  */
Packit 0021fb
struct protolib {
Packit 0021fb
	/* Other libraries to look through if the definition is not
Packit 0021fb
	 * found here.  Note that due to the way imports are stored,
Packit 0021fb
	 * there is no way to distinguish where exactly (at which
Packit 0021fb
	 * place of the config file) the import was made.  */
Packit 0021fb
	struct vect imports;
Packit 0021fb
Packit 0021fb
	/* Dictionary of name->struct prototype.  */
Packit 0021fb
	struct dict prototypes;
Packit 0021fb
Packit 0021fb
	/* Dictionary of name->struct named_type.  */
Packit 0021fb
	struct dict named_types;
Packit 0021fb
Packit 0021fb
	/* Reference count.  */
Packit 0021fb
	unsigned refs;
Packit 0021fb
};
Packit 0021fb
Packit 0021fb
/* Initialize PLIB.  */
Packit 0021fb
void protolib_init(struct protolib *plib);
Packit 0021fb
Packit 0021fb
/* Destroy PLIB.  */
Packit 0021fb
void protolib_destroy(struct protolib *plib);
Packit 0021fb
Packit 0021fb
/* Push IMPORT to PLIB.  Returns 0 on success or a negative value on
Packit 0021fb
 * failure.  In particular, -2 is returned if mutual import is
Packit 0021fb
 * detected.  */
Packit 0021fb
int protolib_add_import(struct protolib *plib, struct protolib *import);
Packit 0021fb
Packit 0021fb
/* Add a prototype PROTO to PLIB.  Returns 0 on success or a negative
Packit 0021fb
 * value on failure.  NAME is owned and released on PLIB destruction
Packit 0021fb
 * if OWN_NAME.  */
Packit 0021fb
int protolib_add_prototype(struct protolib *plib,
Packit 0021fb
			   const char *name, int own_name,
Packit 0021fb
			   struct prototype *proto);
Packit 0021fb
Packit 0021fb
/* Add a named type NAMED to PLIB.  Returns 0 on success or a negative
Packit 0021fb
 * value on failure.  NAME is owned and released on PLIB destruction
Packit 0021fb
 * if OWN_NAME.  NAMED _pointer_ is copied to PLIB.  */
Packit 0021fb
int protolib_add_named_type(struct protolib *plib,
Packit 0021fb
			    const char *name, int own_name,
Packit 0021fb
			    struct named_type *named);
Packit 0021fb
Packit 0021fb
/* Lookup prototype named NAME in PLIB.  If none is found and IMPORTS
Packit 0021fb
 * is true, look recursively in each of the imports.  Returns the
Packit 0021fb
 * corresponding prototype, or NULL if none was found.  */
Packit 0021fb
struct prototype *protolib_lookup_prototype(struct protolib *plib,
Packit 0021fb
					    const char *name, bool imports);
Packit 0021fb
Packit 0021fb
/* Add a named type NAMED to PLIB.  Returns 0 on success or a negative
Packit 0021fb
 * value on failure.  */
Packit 0021fb
int protolib_add_type(struct protolib *plib, struct named_type *named);
Packit 0021fb
Packit 0021fb
/* Lookup type named NAME in PLIB.  If none is found and IMPORTS is
Packit 0021fb
 * true, look recursively in each of the imports.  Returns the
Packit 0021fb
 * corresponding type, or NULL if none was found.  */
Packit 0021fb
struct named_type *protolib_lookup_type(struct protolib *plib,
Packit 0021fb
					const char *name, bool imports);
Packit 0021fb
Packit 0021fb
/* A cache of prototype libraries.  Can load prototype libraries on
Packit 0021fb
 * demand.
Packit 0021fb
 *
Packit 0021fb
 * XXX ltrace should open one config per ABI, which maps long, int,
Packit 0021fb
 * etc. to uint32_t etc.  It would also map char to either of
Packit 0021fb
 * {u,}int8_t.  Other protolibs would have this as implicit import.
Packit 0021fb
 * That would mean that the cache needs ABI tagging--each ABI should
Packit 0021fb
 * have a separate prototype cache, because the types will potentially
Packit 0021fb
 * differ between the ABI's.  protolib cache would then naturally be
Packit 0021fb
 * stored in the ABI object, when this is introduced.  */
Packit 0021fb
struct protolib_cache {
Packit 0021fb
	/* Dictionary of filename->protolib*.  */
Packit 0021fb
	struct dict protolibs;
Packit 0021fb
Packit 0021fb
	/* Fake module for implicit imports.  This is populated by all
Packit 0021fb
	 * files coming from -F.  When -F is empty, it also contains
Packit 0021fb
	 * either $HOME/.ltrace.conf, or /etc/ltrace.conf (whichever
Packit 0021fb
	 * comes first).  */
Packit 0021fb
	struct protolib imports;
Packit 0021fb
Packit 0021fb
	/* For tracking uses of cache during cache's own
Packit 0021fb
	 * initialization.  */
Packit 0021fb
	int bootstrap : 1;
Packit 0021fb
};
Packit 0021fb
Packit 0021fb
/* Initialize CACHE.  Returns 0 on success or a negative value on
Packit 0021fb
 * failure.  */
Packit 0021fb
int protolib_cache_init(struct protolib_cache *cache,
Packit 0021fb
			struct protolib *import);
Packit 0021fb
Packit 0021fb
/* Destroy CACHE.  */
Packit 0021fb
void protolib_cache_destroy(struct protolib_cache *cache);
Packit 0021fb
Packit 0021fb
/* Get protolib corresponding to KEY from CACHE.  KEY would typically
Packit 0021fb
 * be the soname of a library for which a protolib should be obtained.
Packit 0021fb
 * If none has been loaded yet, load a new protolib, cache and return
Packit 0021fb
 * it.  Returns NULL for failures.
Packit 0021fb
 *
Packit 0021fb
 * Protolibs are loaded from a config directory.  If -F contains
Packit 0021fb
 * directory names, those are checked first.  Next, os_get_config_dirs
Packit 0021fb
 * callback is used to get a list of directories to look into.  In the
Packit 0021fb
 * first round, if ALLOW_PRIVATE, ltrace looks in user's private
Packit 0021fb
 * directories.  If the config file wasn't found, the second round is
Packit 0021fb
 * made through system directories.  In each directory, ltrace looks
Packit 0021fb
 * and reads the file named KEY.conf.
Packit 0021fb
 *
Packit 0021fb
 * If the config file still wasn't found, an empty (but non-NULL)
Packit 0021fb
 * protolib is provided instead.  That is augmented with the following
Packit 0021fb
 * imports:
Packit 0021fb
 *
Packit 0021fb
 * - Legacy typedefs
Packit 0021fb
 * - The IMPORT argument passed to protolib_cache_init, if non-NULL
Packit 0021fb
 * - $HOME/.ltrace.conf if available
Packit 0021fb
 * - @sysconfdir@/ltrace.conf if available
Packit 0021fb
 * - Any configure _files_ passed in -F
Packit 0021fb
 *
Packit 0021fb
 * This function returns either the loaded protolib, or NULL when
Packit 0021fb
 * there was an error.  */
Packit 0021fb
struct protolib *protolib_cache_load(struct protolib_cache *cache,
Packit 0021fb
				     const char *key, int own_key,
Packit 0021fb
				     bool allow_private);
Packit 0021fb
Packit 0021fb
/* This is similar to protolib_cache_load, except that if a protolib
Packit 0021fb
 * is not found NULL is returned instead of a default module.
Packit 0021fb
 *
Packit 0021fb
 * It returns 0 for success and a negative value for failure, and the
Packit 0021fb
 * actual return value is passed via *RET.*/
Packit 0021fb
int protolib_cache_maybe_load(struct protolib_cache *cache,
Packit 0021fb
			      const char *key, int own_key,
Packit 0021fb
			      bool allow_private,
Packit 0021fb
			      struct protolib **ret);
Packit 0021fb
Packit 0021fb
/* This is similar to protolib_cache_load, but instead of looking for
Packit 0021fb
 * the file to load in directories, the filename is given.  */
Packit 0021fb
struct protolib *protolib_cache_file(struct protolib_cache *cache,
Packit 0021fb
				     const char *filename, int own_filename);
Packit 0021fb
Packit 0021fb
/* This caches a default module.  This is what protolib_cache_load
Packit 0021fb
 * calls if it fails to find the actual protolib.  Returns default
Packit 0021fb
 * protolib or NULL if there was an error.  */
Packit 0021fb
struct protolib *protolib_cache_default(struct protolib_cache *cache,
Packit 0021fb
					const char *key, int own_key);
Packit 0021fb
Packit 0021fb
/* This is similar to protolib_cache_file, but the library to cache is
Packit 0021fb
 * given in argument.  Returns 0 on success or a negative value on
Packit 0021fb
 * failure.  PLIB is thereafter owned by CACHE.  */
Packit 0021fb
int protolib_cache_protolib(struct protolib_cache *cache,
Packit 0021fb
			    const char *filename, int own_filename,
Packit 0021fb
			    struct protolib *plib);
Packit 0021fb
Packit 0021fb
/* Single global prototype cache.
Packit 0021fb
 *
Packit 0021fb
 * XXX Eventually each ABI should have its own cache.  The idea is
Packit 0021fb
 * that there's one per-ABI config file that all others use for
Packit 0021fb
 * elementary typedefs (long, char, size_t).  Ltrace then only deals
Packit 0021fb
 * in fixed-width integral types (and pointers etc.).  */
Packit 0021fb
extern struct protolib_cache g_protocache;
Packit 0021fb
Packit 0021fb
void init_global_config(void);
Packit 0021fb
Packit 0021fb
#endif /* _PROTOTYPE_H_ */