LCOV - code coverage report
Current view: top level - strace_git - qualify.c (source / functions) Hit Total Coverage
Test: strace-4.16.0.69.f1ea-dirty Code Coverage Lines: 259 261 99.2 %
Date: 2017-03-18 00:38:52 Functions: 29 29 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 169 170 99.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
       3                 :            :  * All rights reserved.
       4                 :            :  *
       5                 :            :  * Redistribution and use in source and binary forms, with or without
       6                 :            :  * modification, are permitted provided that the following conditions
       7                 :            :  * are met:
       8                 :            :  * 1. Redistributions of source code must retain the above copyright
       9                 :            :  *    notice, this list of conditions and the following disclaimer.
      10                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer in the
      12                 :            :  *    documentation and/or other materials provided with the distribution.
      13                 :            :  * 3. The name of the author may not be used to endorse or promote products
      14                 :            :  *    derived from this software without specific prior written permission.
      15                 :            :  *
      16                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      17                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      20                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      21                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      22                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      23                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      24                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      25                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26                 :            :  */
      27                 :            : 
      28                 :            : #include "defs.h"
      29                 :            : #include "nsig.h"
      30                 :            : 
      31                 :            : typedef unsigned int number_slot_t;
      32                 :            : #define BITS_PER_SLOT (sizeof(number_slot_t) * 8)
      33                 :            : 
      34                 :            : struct number_set {
      35                 :            :         number_slot_t *vec;
      36                 :            :         unsigned int nslots;
      37                 :            :         bool not;
      38                 :            : };
      39                 :            : 
      40                 :            : struct number_set read_set;
      41                 :            : struct number_set write_set;
      42                 :            : struct number_set signal_set;
      43                 :            : 
      44                 :            : static struct number_set abbrev_set[SUPPORTED_PERSONALITIES];
      45                 :            : static struct number_set inject_set[SUPPORTED_PERSONALITIES];
      46                 :            : static struct number_set raw_set[SUPPORTED_PERSONALITIES];
      47                 :            : static struct number_set trace_set[SUPPORTED_PERSONALITIES];
      48                 :            : static struct number_set verbose_set[SUPPORTED_PERSONALITIES];
      49                 :            : 
      50                 :            : static void
      51                 :     808803 : number_setbit(const unsigned int i, number_slot_t *const vec)
      52                 :            : {
      53                 :     808803 :         vec[i / BITS_PER_SLOT] |= (number_slot_t) 1 << (i % BITS_PER_SLOT);
      54                 :     808803 : }
      55                 :            : 
      56                 :            : static bool
      57                 :   19199310 : number_isset(const unsigned int i, const number_slot_t *const vec)
      58                 :            : {
      59                 :   19199310 :         return vec[i / BITS_PER_SLOT] & ((number_slot_t) 1 << (i % BITS_PER_SLOT));
      60                 :            : }
      61                 :            : 
      62                 :            : static void
      63                 :     808803 : reallocate_number_set(struct number_set *const set, const unsigned int new_nslots)
      64                 :            : {
      65         [ +  + ]:     808803 :         if (new_nslots <= set->nslots)
      66                 :     697704 :                 return;
      67                 :     111099 :         set->vec = xreallocarray(set->vec, new_nslots, sizeof(*set->vec));
      68                 :     111099 :         memset(set->vec + set->nslots, 0,
      69                 :     111099 :                sizeof(*set->vec) * (new_nslots - set->nslots));
      70                 :     111099 :         set->nslots = new_nslots;
      71                 :            : }
      72                 :            : 
      73                 :            : static void
      74                 :     808803 : add_number_to_set(const unsigned int number, struct number_set *const set)
      75                 :            : {
      76                 :     808803 :         reallocate_number_set(set, number / BITS_PER_SLOT + 1);
      77                 :     808803 :         number_setbit(number, set->vec);
      78                 :     808803 : }
      79                 :            : 
      80                 :            : bool
      81                 :   73617494 : is_number_in_set(const unsigned int number, const struct number_set *const set)
      82                 :            : {
      83                 :   73617494 :         return ((number / BITS_PER_SLOT < set->nslots)
      84 [ +  + ][ +  + ]:   73617494 :                 && number_isset(number, set->vec)) ^ set->not;
      85                 :            : }
      86                 :            : 
      87                 :            : typedef int (*string_to_uint_func)(const char *);
      88                 :            : 
      89                 :            : /*
      90                 :            :  * Add numbers to SET according to STR specification.
      91                 :            :  */
      92                 :            : static void
      93                 :      10349 : qualify_tokens(const char *const str, struct number_set *const set,
      94                 :            :                string_to_uint_func func, const char *const name)
      95                 :            : {
      96                 :            :         /* Clear the set. */
      97         [ +  + ]:      10349 :         if (set->nslots)
      98                 :         12 :                 memset(set->vec, 0, sizeof(*set->vec) * set->nslots);
      99                 :      10349 :         set->not = false;
     100                 :            : 
     101                 :            :         /*
     102                 :            :          * Each leading ! character means inversion
     103                 :            :          * of the remaining specification.
     104                 :            :          */
     105                 :      10349 :         const char *s = str;
     106                 :            : handle_inversion:
     107         [ +  + ]:      29504 :         while (*s == '!') {
     108                 :       9770 :                 set->not = !set->not;
     109                 :       9770 :                 ++s;
     110                 :            :         }
     111                 :            : 
     112         [ +  + ]:      19734 :         if (strcmp(s, "none") == 0) {
     113                 :            :                 /*
     114                 :            :                  * No numbers are added to the set.
     115                 :            :                  * Subsequent is_number_in_set invocations will return set->not.
     116                 :            :                  */
     117                 :       9536 :                 return;
     118         [ +  + ]:      10198 :         } else if (strcmp(s, "all") == 0) {
     119                 :       9385 :                 s = "!none";
     120                 :       9385 :                 goto handle_inversion;
     121                 :            :         }
     122                 :            : 
     123                 :            :         /*
     124                 :            :          * Split the string into comma separated tokens.
     125                 :            :          * For each token, find out the corresponding number
     126                 :            :          * by calling FUNC, and add that number to the set.
     127                 :            :          * The absence of tokens or a negative answer
     128                 :            :          * from FUNC is a fatal error.
     129                 :            :          */
     130                 :        813 :         char *copy = xstrdup(s);
     131                 :        813 :         char *saveptr = NULL;
     132                 :            :         const char *token;
     133                 :        813 :         int number = -1;
     134                 :            : 
     135         [ +  + ]:      14436 :         for (token = strtok_r(copy, ",", &saveptr); token;
     136                 :      13623 :              token = strtok_r(NULL, ",", &saveptr)) {
     137                 :      13707 :                 number = func(token);
     138         [ +  + ]:      13707 :                 if (number < 0) {
     139                 :         84 :                         error_msg_and_die("invalid %s '%s'", name, token);
     140                 :            :                 }
     141                 :            : 
     142                 :      13623 :                 add_number_to_set(number, set);
     143                 :            :         }
     144                 :            : 
     145                 :        729 :         free(copy);
     146                 :            : 
     147         [ +  + ]:        729 :         if (number < 0) {
     148                 :        729 :                 error_msg_and_die("invalid %s '%s'", name, str);
     149                 :            :         }
     150                 :            : }
     151                 :            : 
     152                 :            : static int
     153                 :       1195 : sigstr_to_uint(const char *s)
     154                 :            : {
     155                 :            :         int i;
     156                 :            : 
     157 [ +  + ][ +  + ]:       1195 :         if (*s >= '0' && *s <= '9')
     158                 :        462 :                 return string_to_uint_upto(s, 255);
     159                 :            : 
     160         [ +  + ]:        733 :         if (strncasecmp(s, "SIG", 3) == 0)
     161                 :        348 :                 s += 3;
     162                 :            : 
     163         [ +  + ]:      16583 :         for (i = 0; i <= 255; ++i) {
     164                 :      16553 :                 const char *name = signame(i);
     165                 :            : 
     166         [ +  + ]:      16553 :                 if (strncasecmp(name, "SIG", 3) != 0)
     167                 :       5730 :                         continue;
     168                 :            : 
     169                 :      10823 :                 name += 3;
     170                 :            : 
     171         [ +  + ]:      10823 :                 if (strcasecmp(name, s) != 0)
     172                 :      10120 :                         continue;
     173                 :            : 
     174                 :        703 :                 return i;
     175                 :            :         }
     176                 :            : 
     177                 :         30 :         return -1;
     178                 :            : }
     179                 :            : 
     180                 :            : static bool
     181                 :       1224 : qualify_syscall_number(const char *s, struct number_set *set)
     182                 :            : {
     183                 :       1224 :         int n = string_to_uint(s);
     184         [ +  + ]:       1224 :         if (n < 0)
     185                 :         18 :                 return false;
     186                 :            : 
     187                 :            :         unsigned int p;
     188                 :       1206 :         bool done = false;
     189                 :            : 
     190         [ +  + ]:       4824 :         for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     191         [ +  + ]:       3618 :                 if ((unsigned) n >= nsyscall_vec[p]) {
     192                 :         72 :                         continue;
     193                 :            :                 }
     194                 :       3546 :                 add_number_to_set(n, &set[p]);
     195                 :       3546 :                 done = true;
     196                 :            :         }
     197                 :            : 
     198                 :       1206 :         return done;
     199                 :            : }
     200                 :            : 
     201                 :            : static unsigned int
     202                 :       8727 : lookup_class(const char *s)
     203                 :            : {
     204                 :            :         static const struct {
     205                 :            :                 const char *name;
     206                 :            :                 unsigned int value;
     207                 :            :         } syscall_class[] = {
     208                 :            :                 { "desc",     TRACE_DESC      },
     209                 :            :                 { "file",     TRACE_FILE      },
     210                 :            :                 { "memory",   TRACE_MEMORY    },
     211                 :            :                 { "process",  TRACE_PROCESS   },
     212                 :            :                 { "signal",   TRACE_SIGNAL    },
     213                 :            :                 { "ipc",      TRACE_IPC       },
     214                 :            :                 { "network",  TRACE_NETWORK   },
     215                 :            :                 { "%desc",    TRACE_DESC      },
     216                 :            :                 { "%file",    TRACE_FILE      },
     217                 :            :                 { "%memory",  TRACE_MEMORY    },
     218                 :            :                 { "%process", TRACE_PROCESS   },
     219                 :            :                 { "%signal",  TRACE_SIGNAL    },
     220                 :            :                 { "%ipc",     TRACE_IPC       },
     221                 :            :                 { "%network", TRACE_NETWORK   },
     222                 :            :                 { "%sched",   TRACE_SCHED     },
     223                 :            :                 { "%clock",   TRACE_CLOCK     },
     224                 :            :                 { "%stat",    TRACE_STAT      },
     225                 :            :         };
     226                 :            : 
     227                 :            :         unsigned int i;
     228         [ +  + ]:     132684 :         for (i = 0; i < ARRAY_SIZE(syscall_class); ++i) {
     229         [ +  + ]:     125578 :                 if (strcmp(s, syscall_class[i].name) == 0) {
     230                 :       1621 :                         return syscall_class[i].value;
     231                 :            :                 }
     232                 :            :         }
     233                 :            : 
     234                 :       7106 :         return 0;
     235                 :            : }
     236                 :            : 
     237                 :            : static bool
     238                 :       8727 : qualify_syscall_class(const char *s, struct number_set *set)
     239                 :            : {
     240                 :       8727 :         const unsigned int n = lookup_class(s);
     241         [ +  + ]:       8727 :         if (!n)
     242                 :       7106 :                 return false;
     243                 :            : 
     244                 :            :         unsigned int p;
     245         [ +  + ]:       6484 :         for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     246                 :            :                 unsigned int i;
     247                 :            : 
     248         [ +  + ]:    2155930 :                 for (i = 0; i < nsyscall_vec[p]; ++i) {
     249         [ +  + ]:    2151067 :                         if (!sysent_vec[p][i].sys_name
     250         [ +  + ]:    1805794 :                             || (sysent_vec[p][i].sys_flags & n) != n) {
     251                 :    1756290 :                                 continue;
     252                 :            :                         }
     253                 :     394777 :                         add_number_to_set(i, &set[p]);
     254                 :            :                 }
     255                 :            :         }
     256                 :            : 
     257                 :       1621 :         return true;
     258                 :            : }
     259                 :            : 
     260                 :            : static bool
     261                 :       7106 : qualify_syscall_name(const char *s, struct number_set *set)
     262                 :            : {
     263                 :            :         unsigned int p;
     264                 :       7106 :         bool found = false;
     265                 :            : 
     266         [ +  + ]:      28424 :         for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     267                 :            :                 unsigned int i;
     268                 :            : 
     269         [ +  + ]:    9450980 :                 for (i = 0; i < nsyscall_vec[p]; ++i) {
     270         [ +  + ]:    9429662 :                         if (!sysent_vec[p][i].sys_name
     271         [ +  + ]:    7916084 :                             || strcmp(s, sysent_vec[p][i].sys_name)) {
     272                 :    9408648 :                                 continue;
     273                 :            :                         }
     274                 :      21014 :                         add_number_to_set(i, &set[p]);
     275                 :      21014 :                         found = true;
     276                 :            :                 }
     277                 :            :         }
     278                 :            : 
     279                 :       7106 :         return found;
     280                 :            : }
     281                 :            : 
     282                 :            : static bool
     283                 :       9951 : qualify_syscall(const char *token, struct number_set *set)
     284                 :            : {
     285 [ +  + ][ +  + ]:       9951 :         if (*token >= '0' && *token <= '9')
     286                 :       1224 :                 return qualify_syscall_number(token, set);
     287                 :       8727 :         return qualify_syscall_class(token, set)
     288 [ +  + ][ +  + ]:       8727 :                || qualify_syscall_name(token, set);
     289                 :            : }
     290                 :            : 
     291                 :            : /*
     292                 :            :  * Add syscall numbers to SETs for each supported personality
     293                 :            :  * according to STR specification.
     294                 :            :  */
     295                 :            : static void
     296                 :      37728 : qualify_syscall_tokens(const char *const str, struct number_set *const set,
     297                 :            :                        const char *const name)
     298                 :            : {
     299                 :            :         /* Clear all sets. */
     300                 :            :         unsigned int p;
     301         [ +  + ]:     150912 :         for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     302         [ -  + ]:     113184 :                 if (set[p].nslots)
     303                 :          0 :                         memset(set[p].vec, 0,
     304                 :          0 :                                sizeof(*set[p].vec) * set[p].nslots);
     305                 :     113184 :                 set[p].not = false;
     306                 :            :         }
     307                 :            : 
     308                 :            :         /*
     309                 :            :          * Each leading ! character means inversion
     310                 :            :          * of the remaining specification.
     311                 :            :          */
     312                 :      37728 :         const char *s = str;
     313                 :            : handle_inversion:
     314         [ +  + ]:      95394 :         while (*s == '!') {
     315         [ +  + ]:     115860 :                 for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     316                 :      86895 :                         set[p].not = !set[p].not;
     317                 :            :                 }
     318                 :      28965 :                 ++s;
     319                 :            :         }
     320                 :            : 
     321         [ +  + ]:      66429 :         if (strcmp(s, "none") == 0) {
     322                 :            :                 /*
     323                 :            :                  * No syscall numbers are added to sets.
     324                 :            :                  * Subsequent is_number_in_set invocations
     325                 :            :                  * will return set[p]->not.
     326                 :            :                  */
     327                 :      29602 :                 return;
     328         [ +  + ]:      36827 :         } else if (strcmp(s, "all") == 0) {
     329                 :      28701 :                 s = "!none";
     330                 :      28701 :                 goto handle_inversion;
     331                 :            :         }
     332                 :            : 
     333                 :            :         /*
     334                 :            :          * Split the string into comma separated tokens.
     335                 :            :          * For each token, call qualify_syscall that will take care
     336                 :            :          * if adding appropriate syscall numbers to sets.
     337                 :            :          * The absence of tokens or a negative return code
     338                 :            :          * from qualify_syscall is a fatal error.
     339                 :            :          */
     340                 :       8126 :         char *copy = xstrdup(s);
     341                 :       8126 :         char *saveptr = NULL;
     342                 :            :         const char *token;
     343                 :       8126 :         bool done = false;
     344                 :            : 
     345         [ +  + ]:      17927 :         for (token = strtok_r(copy, ",", &saveptr); token;
     346                 :       9801 :              token = strtok_r(NULL, ",", &saveptr)) {
     347                 :       9951 :                 done = qualify_syscall(token, set);
     348         [ +  + ]:       9951 :                 if (!done) {
     349                 :        150 :                         error_msg_and_die("invalid %s '%s'", name, token);
     350                 :            :                 }
     351                 :            :         }
     352                 :            : 
     353                 :       7976 :         free(copy);
     354                 :            : 
     355         [ +  + ]:       7976 :         if (!done) {
     356                 :       7976 :                 error_msg_and_die("invalid %s '%s'", name, str);
     357                 :            :         }
     358                 :            : }
     359                 :            : 
     360                 :            : /*
     361                 :            :  * Returns NULL if STR does not start with PREFIX,
     362                 :            :  * or a pointer to the first char in STR after PREFIX.
     363                 :            :  */
     364                 :            : static const char *
     365                 :       6903 : strip_prefix(const char *prefix, const char *str)
     366                 :            : {
     367                 :       6903 :         size_t len = strlen(prefix);
     368                 :            : 
     369         [ +  + ]:       6903 :         return strncmp(prefix, str, len) ? NULL : str + len;
     370                 :            : }
     371                 :            : 
     372                 :            : static int
     373                 :       1244 : find_errno_by_name(const char *name)
     374                 :            : {
     375                 :            :         unsigned int i;
     376                 :            : 
     377         [ +  + ]:     116960 :         for (i = 1; i < nerrnos; ++i) {
     378 [ +  + ][ +  + ]:     116804 :                 if (errnoent[i] && (strcasecmp(name, errnoent[i]) == 0))
     379                 :       1088 :                         return i;
     380                 :            :         }
     381                 :            : 
     382                 :        156 :         return -1;
     383                 :            : }
     384                 :            : 
     385                 :            : static bool
     386                 :       4669 : parse_inject_token(const char *const token, struct inject_opts *const fopts,
     387                 :            :                    const bool fault_tokens_only)
     388                 :            : {
     389                 :            :         const char *val;
     390                 :            :         int intval;
     391                 :            : 
     392         [ +  + ]:       4669 :         if ((val = strip_prefix("when=", token))) {
     393                 :            :                 /*
     394                 :            :                  *      == 1+1
     395                 :            :                  * F    == F+0
     396                 :            :                  * F+   == F+1
     397                 :            :                  * F+S
     398                 :            :                  */
     399                 :            :                 char *end;
     400                 :       2603 :                 intval = string_to_uint_ex(val, &end, 0xffff, "+");
     401         [ +  + ]:       2603 :                 if (intval < 1)
     402                 :        312 :                         return false;
     403                 :            : 
     404                 :       2435 :                 fopts->first = intval;
     405                 :            : 
     406         [ +  + ]:       2435 :                 if (*end) {
     407                 :       2066 :                         val = end + 1;
     408         [ +  + ]:       2066 :                         if (*val) {
     409                 :            :                                 /* F+S */
     410                 :       1751 :                                 intval = string_to_uint_upto(val, 0xffff);
     411         [ +  + ]:       1751 :                                 if (intval < 1)
     412                 :        144 :                                         return false;
     413                 :       1607 :                                 fopts->step = intval;
     414                 :            :                         } else {
     415                 :            :                                 /* F+ == F+1 */
     416                 :       1922 :                                 fopts->step = 1;
     417                 :            :                         }
     418                 :            :                 } else {
     419                 :            :                         /* F == F+0 */
     420                 :       2291 :                         fopts->step = 0;
     421                 :            :                 }
     422         [ +  + ]:       2066 :         } else if ((val = strip_prefix("error=", token))) {
     423         [ +  + ]:       1916 :                 if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT)
     424                 :         24 :                         return false;
     425                 :       1892 :                 intval = string_to_uint_upto(val, MAX_ERRNO_VALUE);
     426         [ +  + ]:       1892 :                 if (intval < 0)
     427                 :       1244 :                         intval = find_errno_by_name(val);
     428         [ +  + ]:       1892 :                 if (intval < 1)
     429                 :        156 :                         return false;
     430                 :       1736 :                 fopts->rval = -intval;
     431 [ +  + ][ +  + ]:        150 :         } else if (!fault_tokens_only && (val = strip_prefix("retval=", token))) {
     432         [ +  + ]:         48 :                 if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT)
     433                 :         12 :                         return false;
     434                 :         36 :                 intval = string_to_uint(val);
     435         [ +  + ]:         36 :                 if (intval < 0)
     436                 :          6 :                         return false;
     437                 :         30 :                 fopts->rval = intval;
     438 [ +  + ][ +  + ]:        102 :         } else if (!fault_tokens_only && (val = strip_prefix("signal=", token))) {
     439                 :         30 :                 intval = sigstr_to_uint(val);
     440 [ +  + ][ +  + ]:         30 :                 if (intval < 1 || intval > NSIG_BYTES * 8)
     441                 :         12 :                         return false;
     442                 :         18 :                 fopts->signo = intval;
     443                 :            :         } else {
     444                 :         72 :                 return false;
     445                 :            :         }
     446                 :            : 
     447                 :       4075 :         return true;
     448                 :            : }
     449                 :            : 
     450                 :            : static char *
     451                 :       3519 : parse_inject_expression(const char *const s, char **buf,
     452                 :            :                         struct inject_opts *const fopts,
     453                 :            :                         const bool fault_tokens_only)
     454                 :            : {
     455                 :       3519 :         char *saveptr = NULL;
     456                 :       3519 :         char *name = NULL;
     457                 :            :         char *token;
     458                 :            : 
     459                 :       3519 :         *buf = xstrdup(s);
     460         [ +  + ]:      11065 :         for (token = strtok_r(*buf, ":", &saveptr); token;
     461                 :       7546 :              token = strtok_r(NULL, ":", &saveptr)) {
     462         [ +  + ]:       8140 :                 if (!name)
     463                 :       3471 :                         name = token;
     464         [ +  + ]:       4669 :                 else if (!parse_inject_token(token, fopts, fault_tokens_only))
     465                 :        594 :                         goto parse_error;
     466                 :            :         }
     467                 :            : 
     468         [ +  + ]:       2925 :         if (name)
     469                 :       2877 :                 return name;
     470                 :            : 
     471                 :            : parse_error:
     472                 :        642 :         free(*buf);
     473                 :       3519 :         return *buf = NULL;
     474                 :            : }
     475                 :            : 
     476                 :            : static void
     477                 :        139 : qualify_read(const char *const str)
     478                 :            : {
     479                 :        139 :         qualify_tokens(str, &read_set, string_to_uint, "descriptor");
     480                 :        109 : }
     481                 :            : 
     482                 :            : static void
     483                 :        145 : qualify_write(const char *const str)
     484                 :            : {
     485                 :        145 :         qualify_tokens(str, &write_set, string_to_uint, "descriptor");
     486                 :        115 : }
     487                 :            : 
     488                 :            : static void
     489                 :      10065 : qualify_signals(const char *const str)
     490                 :            : {
     491                 :      10065 :         qualify_tokens(str, &signal_set, sigstr_to_uint, "signal");
     492                 :      10017 : }
     493                 :            : 
     494                 :            : static void
     495                 :      15056 : qualify_trace(const char *const str)
     496                 :            : {
     497                 :      15056 :         qualify_syscall_tokens(str, trace_set, "system call");
     498                 :      15002 : }
     499                 :            : 
     500                 :            : static void
     501                 :       9678 : qualify_abbrev(const char *const str)
     502                 :            : {
     503                 :       9678 :         qualify_syscall_tokens(str, abbrev_set, "system call");
     504                 :       9678 : }
     505                 :            : 
     506                 :            : static void
     507                 :       9511 : qualify_verbose(const char *const str)
     508                 :            : {
     509                 :       9511 :         qualify_syscall_tokens(str, verbose_set, "system call");
     510                 :       9511 : }
     511                 :            : 
     512                 :            : static void
     513                 :        750 : qualify_raw(const char *const str)
     514                 :            : {
     515                 :        750 :         qualify_syscall_tokens(str, raw_set, "system call");
     516                 :        750 : }
     517                 :            : 
     518                 :            : static void
     519                 :       3519 : qualify_inject_common(const char *const str,
     520                 :            :                       const bool fault_tokens_only,
     521                 :            :                       const char *const description)
     522                 :            : {
     523                 :       3519 :         struct inject_opts opts = {
     524                 :            :                 .first = 1,
     525                 :            :                 .step = 1,
     526                 :            :                 .rval = INJECT_OPTS_RVAL_DEFAULT,
     527                 :            :                 .signo = 0
     528                 :            :         };
     529                 :       3519 :         char *buf = NULL;
     530                 :       3519 :         char *name = parse_inject_expression(str, &buf, &opts, fault_tokens_only);
     531         [ +  + ]:       3519 :         if (!name) {
     532                 :        642 :                 error_msg_and_die("invalid %s '%s'", description, str);
     533                 :            :         }
     534                 :            : 
     535                 :            :         /* If neither of retval, error, or signal is specified, then ... */
     536 [ +  + ][ +  + ]:       2877 :         if (opts.rval == INJECT_OPTS_RVAL_DEFAULT && !opts.signo) {
     537         [ +  + ]:       1141 :                 if (fault_tokens_only) {
     538                 :            :                         /* in fault= syntax the default error code is ENOSYS. */
     539                 :        997 :                         opts.rval = -ENOSYS;
     540                 :            :                 } else {
     541                 :            :                         /* in inject= syntax this is not allowed. */
     542                 :        144 :                         error_msg_and_die("invalid %s '%s'", description, str);
     543                 :            :                 }
     544                 :            :         }
     545                 :            : 
     546                 :            :         struct number_set tmp_set[SUPPORTED_PERSONALITIES];
     547                 :       2733 :         memset(tmp_set, 0, sizeof(tmp_set));
     548                 :       2733 :         qualify_syscall_tokens(name, tmp_set, description);
     549                 :            : 
     550                 :       2601 :         free(buf);
     551                 :            : 
     552                 :            :         /*
     553                 :            :          * Initialize inject_vec accourding to tmp_set.
     554                 :            :          * Merge tmp_set into inject_set.
     555                 :            :          */
     556                 :            :         unsigned int p;
     557         [ +  + ]:      10404 :         for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
     558 [ +  + ][ +  + ]:       7803 :                 if (!tmp_set[p].nslots && !tmp_set[p].not) {
     559                 :        186 :                         continue;
     560                 :            :                 }
     561                 :            : 
     562         [ +  + ]:       7617 :                 if (!inject_vec[p]) {
     563                 :       7191 :                         inject_vec[p] = xcalloc(nsyscall_vec[p],
     564                 :            :                                                sizeof(*inject_vec[p]));
     565                 :            :                 }
     566                 :            : 
     567                 :            :                 unsigned int i;
     568         [ +  + ]:    3376870 :                 for (i = 0; i < nsyscall_vec[p]; ++i) {
     569         [ +  + ]:    3369253 :                         if (is_number_in_set(i, &tmp_set[p])) {
     570                 :     375843 :                                 add_number_to_set(i, &inject_set[p]);
     571                 :     375843 :                                 inject_vec[p][i] = opts;
     572                 :            :                         }
     573                 :            :                 }
     574                 :            : 
     575                 :       7617 :                 free(tmp_set[p].vec);
     576                 :            :         }
     577                 :       2601 : }
     578                 :            : 
     579                 :            : static void
     580                 :       3015 : qualify_fault(const char *const str)
     581                 :            : {
     582                 :       3015 :         qualify_inject_common(str, true, "fault argument");
     583                 :       2577 : }
     584                 :            : 
     585                 :            : static void
     586                 :        504 : qualify_inject(const char *const str)
     587                 :            : {
     588                 :        504 :         qualify_inject_common(str, false, "inject argument");
     589                 :         24 : }
     590                 :            : 
     591                 :            : static const struct qual_options {
     592                 :            :         const char *name;
     593                 :            :         void (*qualify)(const char *);
     594                 :            : } qual_options[] = {
     595                 :            :         { "trace",    qualify_trace   },
     596                 :            :         { "t",                qualify_trace   },
     597                 :            :         { "abbrev",   qualify_abbrev  },
     598                 :            :         { "a",                qualify_abbrev  },
     599                 :            :         { "verbose",  qualify_verbose },
     600                 :            :         { "v",                qualify_verbose },
     601                 :            :         { "raw",      qualify_raw     },
     602                 :            :         { "x",                qualify_raw     },
     603                 :            :         { "signal",   qualify_signals },
     604                 :            :         { "signals",  qualify_signals },
     605                 :            :         { "s",                qualify_signals },
     606                 :            :         { "read",     qualify_read    },
     607                 :            :         { "reads",    qualify_read    },
     608                 :            :         { "r",                qualify_read    },
     609                 :            :         { "write",    qualify_write   },
     610                 :            :         { "writes",   qualify_write   },
     611                 :            :         { "w",                qualify_write   },
     612                 :            :         { "fault",    qualify_fault   },
     613                 :            :         { "inject",   qualify_inject  },
     614                 :            : };
     615                 :            : 
     616                 :            : void
     617                 :      48863 : qualify(const char *str)
     618                 :            : {
     619                 :      48863 :         const struct qual_options *opt = qual_options;
     620                 :            :         unsigned int i;
     621                 :            : 
     622         [ +  + ]:     278938 :         for (i = 0; i < ARRAY_SIZE(qual_options); ++i) {
     623                 :     277687 :                 const char *p = qual_options[i].name;
     624                 :     277687 :                 unsigned int len = strlen(p);
     625                 :            : 
     626 [ +  + ][ +  + ]:     277687 :                 if (strncmp(str, p, len) || str[len] != '=')
     627                 :     230075 :                         continue;
     628                 :            : 
     629                 :      47612 :                 opt = &qual_options[i];
     630                 :      47612 :                 str += len + 1;
     631                 :      47612 :                 break;
     632                 :            :         }
     633                 :            : 
     634                 :      48863 :         opt->qualify(str);
     635                 :      47783 : }
     636                 :            : 
     637                 :            : unsigned int
     638                 :   14037668 : qual_flags(const unsigned int scno)
     639                 :            : {
     640                 :   14037668 :         return  (is_number_in_set(scno, &trace_set[current_personality])
     641                 :   14037668 :                    ? QUAL_TRACE : 0)
     642                 :   14037668 :                 | (is_number_in_set(scno, &abbrev_set[current_personality])
     643         [ +  + ]:   14037668 :                    ? QUAL_ABBREV : 0)
     644                 :   14037668 :                 | (is_number_in_set(scno, &verbose_set[current_personality])
     645         [ +  + ]:   14037668 :                    ? QUAL_VERBOSE : 0)
     646                 :   14037668 :                 | (is_number_in_set(scno, &raw_set[current_personality])
     647         [ +  + ]:   14037668 :                    ? QUAL_RAW : 0)
     648                 :   28075336 :                 | (is_number_in_set(scno, &inject_set[current_personality])
     649         [ +  + ]:   14037668 :                    ? QUAL_INJECT : 0);
     650                 :            : }

Generated by: LCOV version 1.12