On Wed, Jun 28, 2017 at 05:56:40AM +0300, Edgar Kaziahmedov wrote: > From: Edgar Kaziahmedov <e...@linux.com> > > The first version of asinfo tool. The asinfo tool has the > following architecture: > architecture dispatcher->system call dispatcher->filter dispatcher > > As for arch. dispatcher, the asinfo has get-arch, list-arch, set-arch > %name_of_arch options, arch_dispatcher is purposed to process them. > Now, to find out the main principle of working, let’s consider the next > one case: > $ asinfo list-syscall set-filter signal > Firstly, arch_dispatcher will return the current architecture, after > that syscall_dispatcher will provide the list of system calls > (struct sc_base_info) for this architecture, finally filter_dispatcher, > working with syscallent’s database, will drop all system calls, which > are not signal-related. > For now, tool is able to show syscall typing its sequence number. > > * Makefile.am (SUBDIRS): Add tools directory. > * configure.ac (AC_CONFIG_FILES): Add Makefile's. > * tools/Makefile.am: New file. > * tools/asinfo/Makefile.am: New file. > * tools/asinfo/arch_list.h: New file. > * tools/asinfo/dispatchers.h: New file. Prototype syscall_dispatcher > and arch_dispatcher. > * tools/asinfo/dispatchers.c: New file. Implement arch_dispatcher. > Import syscallent.h files. > * tools/asinfo/arch_interface.h: New file. Prototype methods to simplify > work with the list of arch_descriptor. Introduce struct arch_descriptor. > * tools/asinfo/arch_interface.c: New file. Implement them. > * tools/asinfo/request_msgs.h: New file. Introduce main type of requests. > Introduce structures for syscall_dispatcher. > * tools/asinfo/asinfo.c: New file. Implement support of all arch options and > initial support of syscall options. > * tools/asinfo/asinfo.1: New file. Empty man. > > Signed-off-by: Edgar Kaziahmedov <e...@linux.com> This and previous commit are signed with different e-mails, is this on purpose?
> --- > Makefile.am | 2 +- > configure.ac | 2 + > tools/Makefile.am | 28 ++++++ > tools/asinfo/Makefile.am | 56 ++++++++++++ > tools/asinfo/arch_interface.c | 101 ++++++++++++++++++++++ > tools/asinfo/arch_interface.h | 75 +++++++++++++++++ > tools/asinfo/arch_list.h | 4 + > tools/asinfo/asinfo.1 | 0 > tools/asinfo/asinfo.c | 192 > ++++++++++++++++++++++++++++++++++++++++++ > tools/asinfo/dispatchers.c | 184 ++++++++++++++++++++++++++++++++++++++++ > tools/asinfo/dispatchers.h | 54 ++++++++++++ > tools/asinfo/request_msgs.h | 80 ++++++++++++++++++ > 12 files changed, 777 insertions(+), 1 deletion(-) > create mode 100644 tools/Makefile.am > create mode 100644 tools/asinfo/Makefile.am > create mode 100644 tools/asinfo/arch_interface.c > create mode 100644 tools/asinfo/arch_interface.h > create mode 100644 tools/asinfo/arch_list.h > create mode 100644 tools/asinfo/asinfo.1 > create mode 100644 tools/asinfo/asinfo.c > create mode 100644 tools/asinfo/dispatchers.c > create mode 100644 tools/asinfo/dispatchers.h > create mode 100644 tools/asinfo/request_msgs.h > > diff --git a/Makefile.am b/Makefile.am > index 233796b6..3dc78eb5 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -35,7 +35,7 @@ endif > if HAVE_MX32_RUNTIME > TESTS_MX32 = tests-mx32 > endif > -SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) > +SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) tools > > bin_PROGRAMS = strace > man_MANS = strace.1 > diff --git a/configure.ac b/configure.ac > index bc7b637d..55fb978d 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -825,6 +825,8 @@ AC_CONFIG_FILES([Makefile > tests/Makefile > tests-m32/Makefile > tests-mx32/Makefile > + tools/Makefile > + tools/asinfo/Makefile > strace.spec > debian/changelog]) > AC_OUTPUT > diff --git a/tools/Makefile.am b/tools/Makefile.am > new file mode 100644 > index 00000000..6044e9ae > --- /dev/null > +++ b/tools/Makefile.am > @@ -0,0 +1,28 @@ > +# Automake input for strace tools. > +# > +# Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# 1. Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# 2. Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# 3. The name of the author may not be used to endorse or promote products > +# derived from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +SUBDIRS = asinfo > diff --git a/tools/asinfo/Makefile.am b/tools/asinfo/Makefile.am > new file mode 100644 > index 00000000..195dfe84 > --- /dev/null > +++ b/tools/asinfo/Makefile.am > @@ -0,0 +1,56 @@ > +# Automake input for strace. "for strace"? > +# > +# Copyright (c) 2017 Edgar Kaziakhmedov <e...@linux.com> > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# 1. Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# 2. Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# 3. The name of the author may not be used to endorse or promote products > +# derived from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +bin_PROGRAMS = asinfo > +man_MANS = asinfo.1 > + > +OS = linux > +ARCH = @arch@ > + > +AM_CFLAGS = $(WARN_CFLAGS) > +AM_CPPFLAGS = -I$(builddir) \ > + -I$(top_builddir)/$(OS) \ > + -I$(top_srcdir)/$(OS) \ > + -I$(top_builddir) \ > + -I$(top_srcdir) > +asinfo_CPPFLAGS = $(AM_CPPFLAGS) > +asinfo_CFLAGS = $(AM_CFLAGS) > + > +asinfo_SOURCES = \ Tabs after space. > + arch_interface.c \ > + arch_interface.h \ > + arch_list.h \ > + asinfo.c \ > + dispatchers.c \ > + dispatchers.h \ > + ../../error_prints.c \ > + ../../error_prints.h \ > + ../../macros.h \ > + requests_msgs.h \ > + ../../xmalloc.c \ > + ../../xmalloc.h \ > + #end of asinfo_SOURCES > diff --git a/tools/asinfo/arch_interface.c b/tools/asinfo/arch_interface.c > new file mode 100644 > index 00000000..3c11beae > --- /dev/null > +++ b/tools/asinfo/arch_interface.c > @@ -0,0 +1,101 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "arch_interface.h" > +#include "xmalloc.h" > + > +struct arch_service *arch_list_create(unsigned size) Shouldn't the argument be called "capacity"? Function return type should be on a separate line. > +{ > + struct arch_service *as = (struct arch_service *) \ Newline escaping is not needed here. > + xcalloc(sizeof(*as), 1); It's better to format line continuation like this: struct arch_service *as = (struct arch_service *) xcalloc(sizeof(*as), 1); Moreover, this cast is not needed. > + if (size) { > + as->arch_list = (struct arch_descriptor **) \ > + xcalloc(sizeof(*(as->arch_list)), size); The same regarding line continuation formatting and cast. > + } Compound statement braces can be omitted in this case. > + as->capacity = size; > + as->next_free = 0; > + return as; > +} > + > +int arch_list_push(struct arch_service *m, struct arch_descriptor *element) Function return type should be on a separate line. > +{ > + if (m->next_free >= m->capacity) { > + return -1; > + } Compound statement braces can be omitted in this case. > + m->arch_list[m->next_free] = element; > + (m->next_free)++; Parentheses are not needed here. > + return 0; > +} > + > +struct arch_descriptor *arch_list_get(struct arch_service *m, unsigned index) Function return type should be on a separate line. > +{ > + if (index >= m->next_free) { > + return NULL; > + } Compound statement braces can be omitted in this case. > + return m->arch_list[index]; > +} > + > +unsigned arch_list_size(struct arch_service *m) Function return type should be on a separate line. > +{ > + return m->next_free; > +} > + > +void arch_list_free(struct arch_service *m) Function return type should be on a separate line. > +{ > + free(m->arch_list); > + free(m); > +} > + > +const char* arch_list_name(struct arch_service *m, unsigned index) Function return type should be on a separate line. > +{ Why there's no next_free check? I'd implement it via arch_list_get with a check for NULL afterwards. > + return m->arch_list[index]->arch_name; > +} > + > +int arch_list_snum(struct arch_service *m, unsigned index) Function return type should be on a separate line. > +{ The same regarding next_free check. > + return m->arch_list[index]->max_scn; > +} > + > +void arch_list_print(struct arch_service *m, const char *delim) Function return type should be on a separate line. > +{ > + unsigned i = 0; > + unsigned max_len = 0; No newline after declarations. > + for (i = 0; i < arch_list_size(m); i++) { > + unsigned temp = strlen(m->arch_list[i]->arch_name); Why direct access if the accessor function was defined? Btw, since arch_name values are static strings, one can calculate their length in compile-time in store in a separate field. So much for premature optimisation. > + if (temp > max_len) { > + max_len = temp; > + } Braces can be omitted here. > + } > + for (i = 0; i < arch_list_size(m); i++) { > + printf("[%u] %*s %s %d\n", i + 1, max_len, arch_list_name(m, i), This output will be unaligned once arch_list_size will be grown up to 11. > + delim, arch_list_snum(m, i)); > + } Braces can be omitted here. > +} > diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h > new file mode 100644 > index 00000000..5e9a8256 > --- /dev/null > +++ b/tools/asinfo/arch_interface.h > @@ -0,0 +1,75 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ Missing newline. > +#ifndef ASINFO_ARCH_INTERFACE > +#define ASINFO_ARCH_INTERFACE > + > +#include "sysent.h" > + > +enum arch_types { "enum arch_type" would be better. > + AARCH64, > + ARM, > + x86_64, > + x32 > +}; > + > +struct arch_descriptor { > + enum arch_types arch_num; > + const char *arch_name; > + int max_scn; > + struct_sysent *list_of_syscall; > +}; > + > +/* To provide push-back interface with arch_list */ > +struct arch_service { > + struct arch_descriptor **arch_list; > + unsigned capacity; > + unsigned next_free; > +}; > + > +#define ARCH_LIST_DEFINE(name) \ > + struct arch_service *(name) > + > +/* Push-back interface is purposed to simplify interaction with > + array of struct arch_descriptor's pointers */ > + > +struct arch_service *arch_list_create(unsigned size); > + > +int arch_list_push(struct arch_service *m, struct arch_descriptor *element); > + > +struct arch_descriptor *arch_list_get(struct arch_service *m, unsigned > index); Oversized line. > + > +unsigned arch_list_size(struct arch_service *m); > + > +void arch_list_free(struct arch_service *m); > + > +const char* arch_list_name(struct arch_service *m, unsigned index); > + > +int arch_list_snum(struct arch_service *m, unsigned index); > + > +void arch_list_print(struct arch_service *m, const char *delim); > + > +#endif /* !ASINFO_ARCH_INTERFACE */ > diff --git a/tools/asinfo/arch_list.h b/tools/asinfo/arch_list.h > new file mode 100644 > index 00000000..4a7accf7 > --- /dev/null > +++ b/tools/asinfo/arch_list.h > @@ -0,0 +1,4 @@ > +[0] = { AARCH64, "aarch64", ARRAY_SIZE(aarch64_sysent0), > aarch64_sysent0 }, > +[1] = { ARM, "arm", ARRAY_SIZE(arm_sysent0), > arm_sysent0 }, > +[2] = { x86_64, "x86_64", ARRAY_SIZE(x86_64_sysent0), > x86_64_sysent0 }, > +[3] = { x32, "x32", ARRAY_SIZE(x32_sysent0), > x32_sysent0 }, You can define utility macro which allows avoiding most of the duplication (assuming that you rename arch names in enum to ARCH_*): #define ARCH_DESC_DEFINE(arch) \ [ARCH_##arch] = { \ .arch_num = ARCH_##arch, \ .arch_name = #arch, \ .max_scn = ARRAY_SIZE(arch##_sysent0), \ .list_of_syscall = arch##_sysent0, \ } \ Moreover, as of now, I do not see why storing this list in a separate file is needed, it is included currently only in a single place and it's not going to be extremely big and frequently-updated. > diff --git a/tools/asinfo/asinfo.1 b/tools/asinfo/asinfo.1 > new file mode 100644 > index 00000000..e69de29b > diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c > new file mode 100644 > index 00000000..020ef7c8 > --- /dev/null > +++ b/tools/asinfo/asinfo.c > @@ -0,0 +1,192 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <stdarg.h> > +#include <stdbool.h> > +#include <string.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <limits.h> It's better to have this list sorted. > + > +#include "arch_interface.h" > +#include "dispatchers.h" > +#include "error_prints.h" > +#include "macros.h" > +#include "request_msgs.h" > +#include "xmalloc.h" > + > +const char *progname; > +static const char *def_delim = ":"; > + > +void ATTRIBUTE_NOINLINE Maybe ATTRIBUTE_NORETURN too? Also, I do not really grasp the need of making this function strictly non-inline. In both cases where this attribute is used in strace.c, the usage is this attribute is justified. > +die(void) > +{ > + exit(1); > +} > + > +/* To calculate sequence number of set bit */ https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup > +static inline unsigned > +fsbit_num(unsigned flag) > +{ > + unsigned i = 0; > + while ((flag >>= 1) != 0) i++; > + return i; > +} > + > +static unsigned > +option_to_request(char *option) > +{ > + const struct opt_to_req requests[] = { static? > + [ 0] = { AD_REQ_SET_ARCH, "set-arch" }, > + [ 1] = { AD_REQ_GET_ARCH, "get-arch" }, > + [ 2] = { AD_REQ_LIST_ARCH, "list-arch" }, > + [ 3] = { SD_REQ_GET_NAME, "get-name" }, > + //[ 4] = { SD_REQ_GET_NUMBER, "get-num" }, > + //[ 5] = { SD_REQ_GET_NARGS, "get-nargs" }, > + //[ 6] = { SD_REQ_GET_PROTO, "get-proto" }, > + //[ 7] = { SD_REQ_GET_KERNEL, "get-kernel" }, > + //[ 8] = { SD_REQ_GET_LIST, "list-syscall" }, > + //[ 9] = { FD_SET_BASE_FILTER, "set-filter" }, > + //[10] = { FD_SET_ADV_FILTER, "set-adv-filter" } Why do you need array indices in this definition? > + }; > + unsigned i; > + > + for (i = 0; i < ARRAY_SIZE(requests); i++) { > + if (strcasecmp(option, requests[i].option) == 0) > + return requests[i].req_t; > + } > + return 0; > +} > + > +static unsigned ATTRIBUTE_NOINLINE Why noinline? > +form_req(int argc, char *argv[], char *args[]) > +{ > + progname = argv[0] ? argv[0] : "asinfo"; I would probably like to check for argc here too, see zerorgc test. > + int i; > + unsigned ret_val = 0; > + unsigned temp_ret = 0; > + unsigned bit_pos = 0; > + > + for (i = 1; i < argc; i++) { > + if ((temp_ret = option_to_request(argv[i])) != 0) { > + if ((ret_val & temp_ret) || > + (!(temp_ret & (SD_REQ_GET_LIST + It's better to use bitwise or and not arithmetic plus here. > + AD_REQ_LIST_ARCH + > + AD_REQ_GET_ARCH)) && > + (i + 1 >= argc))) { > + error_msg_and_help("option '%s' requires " > + "argument", argv[i]); $ ./asinfo get-name 0 get-name 1 ./asinfo: option 'get-name' requires argument Try './asinfo -h' for more information. $ > + } > + ret_val |= temp_ret; > + bit_pos = fsbit_num(temp_ret); > + if (!(temp_ret & (SD_REQ_GET_LIST + AD_REQ_LIST_ARCH + > + AD_REQ_GET_ARCH))) { Since this check is here for the second time, I think it can be refactored and the related flag can be a part of some request description struct. > + args[bit_pos] = argv[i + 1]; > + i += 1; > + } > + } else { > + error_msg_and_help("unrecognized option '%s'", argv[i]); > + } > + } > + return ret_val; > +} > + > +static int > +check_req(unsigned *request, char *args[]) > +{ > + int a_flag = *request & (AD_REQ_MASK ^ AD_REQ_SET_ARCH); > + int s_flag = *request & SD_REQ_MASK; > + int dump = 1; > + /* Check arch flags */ > + if (!(*request & AD_REQ_MASK)) { > + *request |= AD_REQ_GET_ARCH; > + dump = 0; > + } > + if (*request & AD_REQ_SET_ARCH) { > + dump = 0; > + } > + /* Check for ambiguity */ > + if (!((*request & AD_REQ_MASK) == AD_REQ_SET_ARCH || > + (*request & AD_REQ_MASK) == AD_REQ_GET_ARCH || > + (*request & AD_REQ_MASK) == AD_REQ_LIST_ARCH)) { > + return -1; > + } > + if (a_flag != 0 && s_flag != 0) { > + return -1; > + } > + /* Check syscall flags, ambiguity */ > + if (!(*request & SD_REQ_MASK)) { > + *request |= SD_REQ_GET_LIST; > + } > + if (!((*request & SD_REQ_MASK) == SD_REQ_GET_NAME || > + (*request & SD_REQ_MASK) == SD_REQ_GET_NUMBER || > + (*request & SD_REQ_MASK) == SD_REQ_GET_LIST)) { > + return -1; > + } > + return dump; > +} This whole function is very cryptic. > + > +int > +main(int argc, char *argv[]) > +{ > + char **input_args = (char**)xcalloc(sizeof(char*), Missing space before xcalloc. Also this cast is not needed. Missing spaces after "char". > + sizeof(unsigned) * CHAR_BIT); Line continuation should be aligned to opening parenthesis of xcalloc call. > + unsigned requests; > + int dump; > + > + if ((requests = form_req(argc, argv, input_args)) == 0) > + error_msg_and_help("must have OPTIONS"); > + if ((dump = check_req(&requests, input_args)) == -1) > + error_msg_and_help("ambiguous options"); > + > + /* arch_dispatcher work */ > + ARCH_LIST_DEFINE(arch_list); > + arch_list = arch_dispatcher(requests, > + input_args[fsbit_num(AD_REQ_SET_ARCH)]); > + if (dump) { > + arch_list_print(arch_list, def_delim); > + goto done; > + } > + if (arch_list_size(arch_list) == 0) { > + error_msg_and_help("unrecognized architecture '%s'", > + input_args[fsbit_num(AD_REQ_SET_ARCH)]); > + } Braces can be omitted here. > + /* syscall_dispatcher work */ > + SYSCALL_LIST_DEFINE(syscall_list); > + syscall_list = syscall_dispatcher(arch_list, requests, > + input_args[fsbit_num(requests & SD_REQ_MASK)]); > + if (syscall_list[0].sys_name != NULL) { > + printf("%s\n", syscall_list[0].sys_name); > + } else { > + error_msg_and_help("unrecognized syscall number '%s'", > + input_args[fsbit_num(requests & SD_REQ_MASK)]); > + } I do not really understand why exactly this logic is realized. For example, how can one lookup syscall statistics ("dump") for a specific architecture? > +done: > + arch_list_free(arch_list); > + free(input_args); There's no need to free allocated memory right before the exit. > + return 0; > +} > diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c > new file mode 100644 > index 00000000..95ca4923 > --- /dev/null > +++ b/tools/asinfo/dispatchers.c > @@ -0,0 +1,184 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <sys/utsname.h> It's better to have this list sorted. > + > +#include "arch_interface.h" > +#include "dispatchers.h" > +#include "macros.h" > +#include "request_msgs.h" > +#include "sysent.h" > +#include "xmalloc.h" > + > +/* Define these shorthand notations to simplify the syscallent files. */ > +/* These flags could be useful to print group of syscalls */ > +#define TD TRACE_DESC > +#define TF TRACE_FILE > +#define TI TRACE_IPC > +#define TN TRACE_NETWORK > +#define TP TRACE_PROCESS > +#define TS TRACE_SIGNAL > +#define TM TRACE_MEMORY > +#define TST TRACE_STAT > +#define TLST TRACE_LSTAT > +#define TFST TRACE_FSTAT > +#define TSTA TRACE_STAT_LIKE > +#define TSF TRACE_STATFS > +#define TFSF TRACE_FSTATFS > +#define TSFA TRACE_STATFS_LIKE > +#define NF SYSCALL_NEVER_FAILS > +#define MA MAX_ARGS > +#define SI STACKTRACE_INVALIDATE_CACHE > +#define SE STACKTRACE_CAPTURE_ON_ENTER > +#define CST COMPAT_SYSCALL_TYPES > + > +/* > + * For the current functionality there is no need > + * to use sen and (*sys_func)() fields in sysent struct > + */ > +#define SEN(syscall_name) 0, NULL > + > +struct_sysent aarch64_sysent0[] = { > +#include "aarch64/syscallent.h" > +}; > + > +struct_sysent arm_sysent0[] = { > +#include "arm/syscallent.h" > +}; > + > +struct_sysent x32_sysent0[] = { > +#include "x32/syscallent.h" > +}; > + > +struct_sysent x86_64_sysent0[] = { > +#include "x86_64/syscallent.h" > +}; > + > +#undef SEN > +#undef TD > +#undef TF > +#undef TI > +#undef TN > +#undef TP > +#undef TS > +#undef TM > +#undef TST > +#undef TLST > +#undef TFST > +#undef TSTA > +#undef TSF > +#undef TFSF > +#undef TSFA > +#undef NF > +#undef MA > +#undef SI > +#undef SE > +#undef CST > + > +struct arch_descriptor architectures[] = { > +#include "arch_list.h" > +}; > + > +struct sc_base_info * > +syscall_dispatcher(struct arch_service *arch, int request_type, > + const char *data) > +{ > + SYSCALL_LIST_DEFINE(syscall_list); > + > + if (request_type & SD_REQ_GET_NAME) { > + long int nsys; > + char *endptr; > + nsys = strtol(data, &endptr, 10); Why base 10? > + if (*endptr != '\0' || nsys < 0 || > + nsys >= arch->arch_list[0]->max_scn) { > + goto fail; > + } $ ./asinfo get-name "" read $ > + SYSCALL_LIST_ALLOC(syscall_list, 1); > + syscall_list[0].sys_name = > + arch->arch_list[0]->list_of_syscall[nsys].sys_name; > + goto done; > + } > + > +fail: > + SYSCALL_LIST_ALLOC(syscall_list, 0); > +done: > + return syscall_list; > +} Why creating a list and populating only a single entry? > + > +struct arch_service * > +arch_dispatcher(unsigned request_type, const char* arch) > +{ > + struct utsname info_uname; > + const char *loc_arch; > + unsigned i; > + ARCH_LIST_DEFINE(arch_list); > + if ((!arch) && (request_type & AD_REQ_SET_ARCH)) { > + goto fail; > + } Braces can be omitted here. > + > + if (request_type & AD_REQ_GET_ARCH) { > + uname(&info_uname); > + for (i = 0; i < ARRAY_SIZE(architectures); i++) { > + loc_arch = architectures[i].arch_name; > + if (strcasestr(info_uname.machine, loc_arch) != NULL) { I really wonder how this will behave in case of mips or powerpc. > + arch_list = arch_list_create(1); > + arch_list_push(arch_list, &(architectures[i])); > + goto done; > + } > + } > + } > + > + if (request_type & AD_REQ_SET_ARCH) { > + for (i = 0; i < ARRAY_SIZE(architectures); i++) { > + loc_arch = architectures[i].arch_name; > + if (strcasestr(arch, loc_arch) != NULL) { > + arch_list = arch_list_create(1); > + arch_list_push(arch_list, &(architectures[i])); > + goto done; > + } > + } This loop is almost identical to the previous one, it should probably be refactored in a separate function. > + } > + > + if (request_type & AD_REQ_LIST_ARCH) { > + arch_list = arch_list_create(ARRAY_SIZE(architectures)); > + for (i = 0; i < ARRAY_SIZE(architectures); i++) { > + arch_list_push(arch_list, &(architectures[i])); > + } > + goto done; > + } > + > +fail: > + arch_list = arch_list_create(0); > +done: > + return arch_list; > +} > diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h > new file mode 100644 > index 00000000..a60f1595 > --- /dev/null > +++ b/tools/asinfo/dispatchers.h > @@ -0,0 +1,54 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef STRACE_ASINFO_COM_SCALLENT > +#define STRACE_ASINFO_COM_SCALLENT > + > +#include "arch_interface.h" > +#include "request_msgs.h" > +#include "sysent.h" > + > +#define SYSCALL_LIST_DEFINE(name) \ > + struct sc_base_info *(name) > + > +#define SYSCALL_LIST_ALLOC(name, size) \ > + (name) = (struct sc_base_info*) xcalloc(sizeof(*(name)), (size + 1)) The cast is not needed here. Missing space after sc_base_info. > + > +/* The main interaction with low-level structures, such as for now, > + * struct_sysent, is happening here, the remaining processing should > + * be done on the other levels. > + */ > +struct sc_base_info *syscall_dispatcher(struct arch_service *arch, > + int request_type, > + const char *arg); > + > +/* The function is purposed to interact with uname syscall > + */ > +struct arch_service *arch_dispatcher(unsigned request_type, > + const char* arch); > + > +#endif /* !STRACE_ASINFO_COM_SCALLENT */ > diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h > new file mode 100644 > index 00000000..575e2735 > --- /dev/null > +++ b/tools/asinfo/request_msgs.h > @@ -0,0 +1,80 @@ > +/* File description will not harm here. > + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef STRACE_ASINFO_REQ_MSGS > +#define STRACE_ASINFO_REQ_MSGS > + > +/* Request types for syscall_dispatcher, > + * arch_dispatcher, and filter_dispatcher, > + * which, in turn, could be combined > + */ > +enum request_types { > + SD_REQ_GET_NAME = 0x1<<0, > + SD_REQ_GET_NUMBER = 0x1<<1, > + SD_REQ_GET_NARGS = 0x1<<2, > + SD_REQ_GET_PROTO = 0x1<<3, > + SD_REQ_GET_KERNEL = 0x1<<4, > + SD_REQ_GET_LIST = 0x1<<5, > + /* Reserved */ > + AD_REQ_SET_ARCH = 0x1<<16, > + AD_REQ_GET_ARCH = 0x1<<17, > + AD_REQ_LIST_ARCH = 0x1<<18, > + /* Reserved */ > + FD_SET_BASE_FILTER = 0x1<<24, > + FD_SET_ADV_FILTER = 0x1<<25 What for is FD, anyway? > +}; > + > +#define SD_REQ_MASK (0x0000FFFFU) > +#define AD_REQ_MASK (0x00FF0000U) > +#define FD_REQ_MASK (0xFF000000U) I'd have simple set of enums which calculate all this stuff for me, like this: enum syscall_req_bit { SD_REQ_GET_NAME_BIT, SD_REQ_GET_NUMBER_BIT, SD_REQ_GET_NARGS_BIT, SD_REQ_GET_PROTO_BIT, SD_REQ_GET_KERNEL_BIT, SD_REQ_GET_LIST_BIT, SYSCALL_REQ_BIT_LAST }; enum arch_req_bit { AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST, AD_REQ_GET_ARCH_BIT, AD_REQ_LIST_ARCH_BIT, ARCH_REQ_BIT_LAST }; enum fd_req_bit { FD_SET_BASE_FILTER_BIT = ARCH_REQ_BIT_LAST, FD_SET_ADV_FILTER, FD_REQ_BIT_LAST }; #define ENUM_FLAG(name) name = name##_BIT enum request_type { ENUM_FLAG(SD_REQ_GET_NAME), ENUM_FLAG(SD_REQ_GET_NUMBER), ENUM_FLAG(SD_REQ_GET_NARGS), ENUM_FLAG(SD_REQ_GET_PROTO), ENUM_FLAG(SD_REQ_GET_KERNEL), ENUM_FLAG(SD_REQ_GET_LIST), ENUM_FLAG(AD_REQ_SET_ARCH), ENUM_FLAG(AD_REQ_GET_ARCH), ENUM_FLAG(AD_REQ_LIST_ARCH), ENUM_FLAG(FD_REQ_SET_BASE_FILTER), ENUM_FLAG(FD_REQ_SET_ADV_FILTER), }; #undef ENUM_FLAG #define BITMASK(hi, lo) (1 << (hi) - 1 << (lo)) #define REQ_LAST_BIT FD_REQ_BIT_LAST /* Can be used in input_args calloc*/ #define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0) #define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST, SYSCALL_REQ_BIT_LAST) #define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST) #undef BITMASK This would also allow avoiding fsbit_num calls with constant operands. > + > +/* To convert options to req_types */ > +struct opt_to_req { > + enum request_types req_t; > + const char *option; > +}; > + > +/* SD_REQ_GET_NAME, SD_REQ_GET_NUMBER */ > +struct sc_base_info { > + int sys_number; > + const char *sys_name; > + int sys_flags; > +}; > + > +/* SD_REQ_GET_NARGS */ > +struct sc_nargs { > + struct sc_base_info sys_bi; > + int nargs; > +}; > + > +/* FD_SET_BASE_FILTER */ > +struct sc_filter { > + struct sc_base_info sys_bi; > + int filter_options; > +}; > + > +#endif /* !STRACE_ASINFO_REQ_MSGS */ > -- > 2.11.0 $ ./asinfo -h ./asinfo: unrecognized option '-h' Try './asinfo -h' for more information. $ Overall, the whole thing now looks over-engineered with no significant reason for that. Maybe future commits which implement more functionality will solve that. ------------------------------------------------------------------------------ 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