Home | History | Annotate | Download | only in ltrace
      1 /*
      2  * This file is part of ltrace.
      3  * Copyright (C) 2011,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 PARAM_H
     22 #define PARAM_H
     23 
     24 #include "forward.h"
     25 
     26 /* The structure param holds information about a parameter of a
     27  * function.  It's used to configure a function prototype.  There are
     28  * two flavors of parameters:
     29  *
     30  *  - simple types
     31  *  - parameter packs
     32  *
     33  * Parameter packs are used to describe various vararg constructs.
     34  * They themselves are parametrized by ltrace expressions.  Those will
     35  * typically be references to other arguments, but constants might
     36  * also make sense, and it principle, anything can be used.  */
     37 
     38 enum param_flavor {
     39 	PARAM_FLAVOR_TYPE,
     40 	PARAM_FLAVOR_PACK,
     41 
     42 	/* This is for emitting arguments in two bunches.  This is
     43 	 * where we should stop emitting "left" bunch.  All that's
     44 	 * after this parameter should be emitted in the "right"
     45 	 * bunch.  */
     46 	PARAM_FLAVOR_STOP,
     47 };
     48 
     49 enum param_pack_flavor {
     50 	/* This parameter pack expands to a list of ordinary
     51 	 * arguments.  For example if the last argument is sometimes
     52 	 * ignored, that would be described by a PARAM_PACK_ARGS
     53 	 * parameter pack.  ioctl or ptrace are two examples that
     54 	 * would benefit from this.  */
     55 	PARAM_PACK_ARGS,
     56 
     57 	/* This parameter pack represents a vararg argument.  */
     58 	PARAM_PACK_VARARGS,
     59 };
     60 
     61 enum param_status {
     62 	PPCB_ERR = -1,	/* An error occurred.  */
     63 	PPCB_STOP,	/* Stop fetching the arguments.  */
     64 	PPCB_CONT,	/* Display this argument and keep going.  */
     65 };
     66 
     67 /* Each parameter enumerator defines its own context object.
     68  * Definitions of these are in respective .c files of each
     69  * enumerator.  */
     70 struct param_enum;
     71 
     72 struct param {
     73 	enum param_flavor flavor;
     74 	union {
     75 		struct {
     76 			struct arg_type_info *type;
     77 			int own_type;
     78 		} type;
     79 		struct {
     80 			struct expr_node *args;
     81 			size_t nargs;
     82 			int own_args;
     83 			enum param_pack_flavor ppflavor;
     84 
     85 			struct param_enum *(*init)(struct value *cb_args,
     86 						   size_t nargs,
     87 						   struct value_dict *arguments);
     88 			int (*next)(struct param_enum *self,
     89 				    struct arg_type_info *info,
     90 				    int *insert_stop);
     91 			enum param_status (*stop)(struct param_enum *self,
     92 						  struct value *value);
     93 			void (*done)(struct param_enum *self);
     94 		} pack;
     95 	} u;
     96 };
     97 
     98 /* Initialize simple type parameter.  TYPE is owned and released by
     99  * PARAM if OWN_TYPE.  */
    100 void param_init_type(struct param *param,
    101 		     struct arg_type_info *type, int own_type);
    102 
    103 /* Initialize a stop.  */
    104 void param_init_stop(struct param *param);
    105 
    106 /* Initialize parameter pack PARAM.  ARGS is an array of expressions
    107  * with parameters.  ARGS is owned and released by the pack if
    108  * OWN_ARGS.  NARGS is number of ARGS.
    109  *
    110  * When the parameter pack should be expanded, those expressions are
    111  * evaluated and passed to the INIT callback.  This has to return a
    112  * non-NULL context object.
    113  *
    114  * The NEXT callback is then called repeatedly, and should initialize
    115  * its INFOP argument to a type of the next parameter in the pack.
    116  * When there are no more parameters in the pack, the NEXT callback
    117  * will set INFOP to a VOID parameter.  If the callback sets
    118  * INSERT_STOP to a non-zero value, a stop parameter shall be inserted
    119  * before this actual parameter.
    120  *
    121  * Core then uses the passed-in type to fetch the next argument, which
    122  * is in turn passed to STOP callback.  This callback then tells
    123  * ltrace core what to do next: whether there are more arguments, and
    124  * if not, whether this argument should be displayed.
    125  *
    126  * After the enumeration is ended, DONE callback is called.  */
    127 void param_init_pack(struct param *param, enum param_pack_flavor ppflavor,
    128 		     struct expr_node *args, size_t nargs, int own_args,
    129 		     struct param_enum *(*init)(struct value *cb_args,
    130 						size_t nargs,
    131 						struct value_dict *arguments),
    132 		     int (*next)(struct param_enum *self,
    133 				 struct arg_type_info *infop,
    134 				 int *insert_stop),
    135 		     enum param_status (*stop)(struct param_enum *self,
    136 					       struct value *value),
    137 		     void (*done)(struct param_enum *self));
    138 
    139 /* Start enumerating types in parameter pack.  This evaluates the
    140  * parameter the pack arguments and calls the init callback.  See the
    141  * documentation of param_init_pack for details.  */
    142 struct param_enum *param_pack_init(struct param *param,
    143 				   struct value_dict *fargs);
    144 
    145 /* Ask for next type in enumeration.  See the documentation of
    146  * param_init_pack for details.  */
    147 int param_pack_next(struct param *param, struct param_enum *self,
    148 		    struct arg_type_info *infop, int *insert_stop);
    149 
    150 /* Ask whether we should stop enumerating.  See the documentation of
    151  * param_init_pack for details.  */
    152 enum param_status param_pack_stop(struct param *param,
    153 				  struct param_enum *self, struct value *value);
    154 
    155 /* Finish enumerating types in parameter pack.  See the documentation
    156  * of param_init_pack for details.  */
    157 void param_pack_done(struct param *param, struct param_enum *self);
    158 
    159 /* Destroy data held by PARAM, but not the PARAM pointer itself.  */
    160 void param_destroy(struct param *param);
    161 
    162 #endif /* PARAM_H */
    163