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