On Thu, Jun 29, 2017 at 02:46:12PM +0700, Nikolay Marchuk wrote:
> * basic_actions.c (parse_inject, parse_fault, apply_fault): Implement.
> (apply_inject): Change inject private data.
> * defs.h (inject_vec): Remove.
> (inject_opts): Add init flag.
> * filter.h (parse_inject_token): Add definition.
> * filter_action.c: Add fault action.
> * filter_qualify.c (parse_inject_common): Generate new inject private data.
> ---
>  basic_actions.c  | 95 
> ++++++++++++++++++++++++++++++++++++++++++++++++++------
>  defs.h           |  2 +-
>  filter.h         |  2 ++
>  filter_action.c  |  3 ++
>  filter_qualify.c | 42 ++++++++++---------------
>  5 files changed, 108 insertions(+), 36 deletions(-)
> 
> diff --git a/basic_actions.c b/basic_actions.c
> index de87cde..1eb597e 100644
> --- a/basic_actions.c
> +++ b/basic_actions.c
> @@ -25,6 +25,7 @@
>   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>   */
>  #include "defs.h"
> +#include "filter.h"
>  
>  bool
>  is_traced(struct tcb *tcp)
> @@ -49,50 +50,134 @@ apply_trace(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_TRACE;
>  }
> +
> +struct inject_priv_data {
> +     struct inject_opts opts;
> +     struct inject_opts **inject_vec;
> +};
> +
>  void
>  apply_inject(struct tcb *tcp, void *_priv_data)
>  {
> -     struct inject_opts **inject_vec = (struct inject_opts **)_priv_data;
> +     struct inject_priv_data *data = (struct inject_priv_data *)_priv_data;
> +     struct inject_opts *opts;
> +     if (!(scno_in_range(tcp->scno) && 
> data->inject_vec[current_personality]))
Overlength line.

> +             return;
> +     opts = &data->inject_vec[current_personality][tcp->scno];
> +     if (!opts->init) {
> +             data->inject_vec[current_personality][tcp->scno] = data->opts;
> +             opts = &data->inject_vec[current_personality][tcp->scno];
> +             opts->init = true;
> +     }
>       tcp->qual_flg |= QUAL_INJECT;
> -     tcp->inject_opts = (scno_in_range(tcp->scno) && 
> inject_vec[current_personality])
Overlength line.

> -            ? &inject_vec[current_personality][tcp->scno] : NULL;
> +     tcp->inject_opts = opts;
>  }
> -void*
> +
> +static void *
> +parse_inject_common_args(const char *const str,
> +                         const bool fault_tokens_only,
> +                         const char *const description)
> +{
> +     struct inject_priv_data *data = xmalloc(sizeof(struct 
> inject_priv_data));
Overlength line.

> +     data->inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
> +                                sizeof(struct inject_opts *));
> +     unsigned int p;
> +     for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
> +             data->inject_vec[p] = xcalloc(nsyscall_vec[p],
> +                                           sizeof(struct inject_opts));
> +     }
> +     data->opts.first = 1;
> +     data->opts.step = 1;
> +     data->opts.rval = INJECT_OPTS_RVAL_DEFAULT;
> +     data->opts.signo = 0;
> +     if (!str) {
> +             if (fault_tokens_only) {
> +                     data->opts.rval = -ENOSYS;
> +                     return data;
> +             } else {
> +                     error_msg_and_die("inject argument is required");
> +             }
> +     }
> +     char *buf = xstrdup(str);
> +     char *saveptr = NULL;
> +     char *token;
> +     for (token = strtok_r(buf, ";", &saveptr); token;
> +          token = strtok_r(NULL, ";", &saveptr)) {
> +             if (!parse_inject_token(token, &data->opts, fault_tokens_only))
> +                     error_msg_and_die("invalid %s argument '%s'",
> +                                       description, token);
> +     }
> +     free(buf);
What bothers me is that this part is essentially the same as
parse_inject_expression (with few minor discrepancies). Is it possible
to refactor it to avoid code duplication?

> +     if (data->opts.rval == INJECT_OPTS_RVAL_DEFAULT && !data->opts.signo) {
> +             if (fault_tokens_only) {
> +                     data->opts.rval = -ENOSYS;
> +             } else {
> +                     error_msg_and_die("invalid %s arguments '%s'",
> +                                       description, str);
> +             }
> +     }
> +     return data;
> +}
> +
> +void *
>  parse_inject(const char *str)
>  {
> -     return NULL;
> +     return parse_inject_common_args(str, false, "inject");
>  }
> +
>  void free_inject(void *_priv_data)
>  {
> -     struct inject_opts **vec = (struct inject_opts **)_priv_data;
> +     struct inject_priv_data *data = (struct inject_priv_data *)_priv_data;
>       unsigned int p;
>       for (p = 0; p < SUPPORTED_PERSONALITIES; ++p)
> -             if (vec[p])
> -                     free(vec[p]);
> -     free(vec);
> +             if (data->inject_vec[p])
> +                     free(data->inject_vec[p]);
> +     free(data->inject_vec);
> +     free(data);
>  }
> +
>  void
>  apply_read(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_READ;
>  }
> +
>  void
>  apply_write(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_WRITE;
>  }
> +
>  void
>  apply_raw(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_RAW;
>  }
> +
>  void
>  apply_abbrev(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_ABBREV;
>  }
> +
>  void
>  apply_verbose(struct tcb *tcp, void *_priv_data)
>  {
>       tcp->qual_flg |= QUAL_VERBOSE;
>  }
> +
> +void *
> +parse_fault(const char *str)
> +{
> +     return parse_inject_common_args(str, true, "fault");
> +}
> +
> +void
> +apply_fault(struct tcb *tcp, void *_priv_data)
> +{
> +     apply_inject(tcp, _priv_data);
> +}
> +
> +void free_fault(void *_priv_data) {
> +     free_inject(_priv_data);
> +}
> diff --git a/defs.h b/defs.h
> index 9242b16..21dec65 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -203,6 +203,7 @@ struct inject_opts {
>       uint16_t step;
>       uint16_t signo;
>       int rval;
> +     bool init;
>  };
>  
>  #define MAX_ERRNO_VALUE                      4095
> @@ -970,7 +971,6 @@ extern unsigned nioctlents;
>  
>  extern const unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES];
>  extern const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES];
> -extern struct inject_opts *inject_vec[SUPPORTED_PERSONALITIES];
>  
>  #ifdef IN_MPERS_BOOTSTRAP
>  /* Transform multi-line MPERS_PRINTER_DECL statements to one-liners.  */
> diff --git a/filter.h b/filter.h
> index ed435c8..7e03d75 100644
> --- a/filter.h
> +++ b/filter.h
> @@ -41,6 +41,8 @@ extern bool is_traced(struct tcb *);
>  typedef int (*string_to_uint_func)(const char *);
>  void parse_set(const char *const, struct number_set *const,
>                 string_to_uint_func, const char *const);
> +bool parse_inject_token(const char *const, struct inject_opts *const,
> +                        const bool);
>  
>  struct filter* add_filter_to_array(struct filter **, unsigned int *nfilters,
>                                     const char *name);
> diff --git a/filter_action.c b/filter_action.c
> index f71f140..fd3fa92 100644
> --- a/filter_action.c
> +++ b/filter_action.c
> @@ -34,6 +34,7 @@ apply_ ## name(struct tcb *, void *)
>  
>  DECL_FILTER_ACTION(trace);
>  DECL_FILTER_ACTION(inject);
> +DECL_FILTER_ACTION(fault);
>  DECL_FILTER_ACTION(read);
>  DECL_FILTER_ACTION(write);
>  DECL_FILTER_ACTION(raw);
> @@ -50,6 +51,7 @@ free_ ## name(void *)
>  
>  DECL_FILTER_ACTION_PARSER(null);
>  DECL_FILTER_ACTION_PARSER(inject);
> +DECL_FILTER_ACTION_PARSER(fault);
>  
>  #undef DECL_FILTER_ACTION_PARSER
>  
> @@ -68,6 +70,7 @@ static const struct filter_action_type {
>  } action_types[] = {
>       FILTER_ACTION_TYPE(trace,       2,      null,   NULL),
>       FILTER_ACTION_TYPE(inject,      2,      inject, NULL),
> +     FILTER_ACTION_TYPE(fault,       2,      fault,  NULL),
>       FILTER_ACTION_TYPE(read,        1,      null,   is_traced),
>       FILTER_ACTION_TYPE(write,       1,      null,   is_traced),
>       FILTER_ACTION_TYPE(raw,         1,      null,   is_traced),
> diff --git a/filter_qualify.c b/filter_qualify.c
> index 6020ce8..79c1202 100644
> --- a/filter_qualify.c
> +++ b/filter_qualify.c
> @@ -80,7 +80,7 @@ sigstr_to_uint(const char *s)
>       return -1;
>  }
>  
> -static bool
> +bool
>  parse_inject_token(const char *const token, struct inject_opts *const fopts,
>                  const bool fault_tokens_only)
>  {
> @@ -233,6 +233,11 @@ parse_raw(const char *const str)
>       set_qualify_mode(action);
>  }
>  
> +struct inject_priv_data {
> +     struct inject_opts opts;
> +     struct inject_opts **inject_vec;
> +};
> +
>  static void
>  parse_inject_common(const char *const str,
>                     const bool fault_tokens_only,
> @@ -242,7 +247,8 @@ parse_inject_common(const char *const str,
>               .first = 1,
>               .step = 1,
>               .rval = INJECT_OPTS_RVAL_DEFAULT,
> -             .signo = 0
> +             .signo = 0,
> +             .init = true
>       };
>       char *buf = NULL;
>       char *name = parse_inject_expression(str, &buf, &opts, 
> fault_tokens_only);
> @@ -265,35 +271,19 @@ parse_inject_common(const char *const str,
>       struct filter *filter = create_filter(action, "syscall");
>       parse_filter(filter, name, description);
>       set_qualify_mode(action);
> -
>       free(buf);
> -     const struct number_set *tmp_set = (const struct number_set *)
> -                                         get_filter_priv_data(filter);
> -     struct inject_opts **inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
> -                                               sizeof(struct inject_opts *));
> -     /*
> -      * Initialize inject_vec accourding to tmp_set.
> -      */
> +
> +     struct inject_priv_data *data = xmalloc(sizeof(struct 
> inject_priv_data));
> +     data->opts = opts;
> +     data->inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
> +                                sizeof(struct inject_opts *));
>  
>       unsigned int p;
>       for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
> -             if (is_empty(&tmp_set[p])) {
> -                     continue;
> -             }
> -
> -             if (!inject_vec[p]) {
> -                     inject_vec[p] = xcalloc(nsyscall_vec[p],
> -                                            sizeof(*inject_vec[p]));
> -             }
> -
> -             unsigned int i;
> -             for (i = 0; i < nsyscall_vec[p]; ++i) {
> -                     if (is_number_in_set(i, &tmp_set[p])) {
> -                             inject_vec[p][i] = opts;
> -                     }
> -             }
> +             data->inject_vec[p] = xcalloc(nsyscall_vec[p],
> +                                           sizeof(struct inject_opts));
>       }
> -     set_filter_action_priv_data(action, inject_vec);
> +     set_filter_action_priv_data(action, data);
>  }
>  
>  static void

Why did you decide to split patches this way, i.e., provide part of the
implementation in the previous patch (like "inject" action) and part
(like "fault" action) here?

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to