|
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_ */
|