LCOV - code coverage report
Current view: top level - strace - util.c (source / functions) Hit Total Coverage
Test: strace-4.18.0.129.97bbb Code Coverage Lines: 452 584 77.4 %
Date: 2017-07-31 03:46:08 Functions: 50 52 96.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 311 466 66.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3                 :            :  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4                 :            :  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5                 :            :  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6                 :            :  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
       7                 :            :  *                     Linux for s390 port by D.J. Barrow
       8                 :            :  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
       9                 :            :  * Copyright (c) 1999-2017 The strace developers.
      10                 :            :  * All rights reserved.
      11                 :            :  *
      12                 :            :  * Redistribution and use in source and binary forms, with or without
      13                 :            :  * modification, are permitted provided that the following conditions
      14                 :            :  * are met:
      15                 :            :  * 1. Redistributions of source code must retain the above copyright
      16                 :            :  *    notice, this list of conditions and the following disclaimer.
      17                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      18                 :            :  *    notice, this list of conditions and the following disclaimer in the
      19                 :            :  *    documentation and/or other materials provided with the distribution.
      20                 :            :  * 3. The name of the author may not be used to endorse or promote products
      21                 :            :  *    derived from this software without specific prior written permission.
      22                 :            :  *
      23                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      24                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      25                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      26                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      27                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      28                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      29                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      30                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      31                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      32                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      33                 :            :  */
      34                 :            : 
      35                 :            : #include "defs.h"
      36                 :            : #include <sys/param.h>
      37                 :            : #include <fcntl.h>
      38                 :            : #include <stdarg.h>
      39                 :            : #ifdef HAVE_SYS_XATTR_H
      40                 :            : # include <sys/xattr.h>
      41                 :            : #endif
      42                 :            : #include <sys/uio.h>
      43                 :            : #include <asm/unistd.h>
      44                 :            : 
      45                 :            : #include "scno.h"
      46                 :            : #include "regs.h"
      47                 :            : #include "ptrace.h"
      48                 :            : 
      49                 :            : int
      50                 :      10987 : string_to_uint_ex(const char *const str, char **const endptr,
      51                 :            :                   const unsigned int max_val, const char *const accepted_ending)
      52                 :            : {
      53                 :            :         char *end;
      54                 :            :         long val;
      55                 :            : 
      56         [ +  + ]:      10987 :         if (!*str)
      57                 :            :                 return -1;
      58                 :            : 
      59                 :      10971 :         errno = 0;
      60                 :      10971 :         val = strtol(str, &end, 10);
      61                 :            : 
      62 [ +  + ][ +  + ]:      10971 :         if (str == end || val < 0 || (unsigned long) val > max_val
                 [ +  + ]
      63 [ -  + ][ #  # ]:      10129 :             || (val == LONG_MAX && errno == ERANGE))
      64                 :            :                 return -1;
      65                 :            : 
      66 [ +  + ][ +  + ]:      10129 :         if (*end && (!accepted_ending || !strchr(accepted_ending, *end)))
         [ -  + ][ #  # ]
         [ #  # ][ +  + ]
      67                 :            :                 return -1;
      68                 :            : 
      69         [ +  + ]:      10101 :         if (endptr)
      70                 :       1422 :                 *endptr = end;
      71                 :            : 
      72                 :      10101 :         return (int) val;
      73                 :            : }
      74                 :            : 
      75                 :            : int
      76                 :       7035 : string_to_uint(const char *const str)
      77                 :            : {
      78                 :       7035 :         return string_to_uint_upto(str, INT_MAX);
      79                 :            : }
      80                 :            : 
      81                 :            : int
      82                 :       5172 : tv_nz(const struct timeval *a)
      83                 :            : {
      84 [ +  - ][ +  - ]:       5172 :         return a->tv_sec || a->tv_usec;
      85                 :            : }
      86                 :            : 
      87                 :            : int
      88                 :      44138 : tv_cmp(const struct timeval *a, const struct timeval *b)
      89                 :            : {
      90         [ +  + ]:      44138 :         if (a->tv_sec < b->tv_sec
      91 [ +  + ][ +  + ]:      44104 :             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
      92                 :            :                 return -1;
      93         [ +  + ]:      44045 :         if (a->tv_sec > b->tv_sec
      94 [ +  - ][ +  + ]:      43993 :             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
      95                 :            :                 return 1;
      96                 :      33549 :         return 0;
      97                 :            : }
      98                 :            : 
      99                 :            : double
     100                 :        188 : tv_float(const struct timeval *tv)
     101                 :            : {
     102                 :        188 :         return tv->tv_sec + tv->tv_usec/1000000.0;
     103                 :            : }
     104                 :            : 
     105                 :            : void
     106                 :       5339 : tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
     107                 :            : {
     108                 :       5339 :         tv->tv_sec = a->tv_sec + b->tv_sec;
     109                 :       5339 :         tv->tv_usec = a->tv_usec + b->tv_usec;
     110         [ -  + ]:       5339 :         if (tv->tv_usec >= 1000000) {
     111                 :          0 :                 tv->tv_sec++;
     112                 :          0 :                 tv->tv_usec -= 1000000;
     113                 :            :         }
     114                 :       5339 : }
     115                 :            : 
     116                 :            : void
     117                 :     130041 : tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
     118                 :            : {
     119                 :     130041 :         tv->tv_sec = a->tv_sec - b->tv_sec;
     120                 :     130041 :         tv->tv_usec = a->tv_usec - b->tv_usec;
     121         [ -  + ]:     130041 :         if (((long) tv->tv_usec) < 0) {
     122                 :          0 :                 tv->tv_sec--;
     123                 :          0 :                 tv->tv_usec += 1000000;
     124                 :            :         }
     125                 :     130041 : }
     126                 :            : 
     127                 :            : void
     128                 :        183 : tv_div(struct timeval *tv, const struct timeval *a, int n)
     129                 :            : {
     130                 :        183 :         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
     131                 :        183 :         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
     132                 :        183 :         tv->tv_usec %= 1000000;
     133                 :        183 : }
     134                 :            : 
     135                 :            : void
     136                 :        183 : tv_mul(struct timeval *tv, const struct timeval *a, int n)
     137                 :            : {
     138                 :        183 :         tv->tv_usec = a->tv_usec * n;
     139                 :        183 :         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
     140                 :        183 :         tv->tv_usec %= 1000000;
     141                 :        183 : }
     142                 :            : 
     143                 :            : #if !defined HAVE_STPCPY
     144                 :            : char *
     145                 :            : stpcpy(char *dst, const char *src)
     146                 :            : {
     147                 :            :         while ((*dst = *src++) != '\0')
     148                 :            :                 dst++;
     149                 :            :         return dst;
     150                 :            : }
     151                 :            : #endif
     152                 :            : 
     153                 :            : /* Find a next bit which is set.
     154                 :            :  * Starts testing at cur_bit.
     155                 :            :  * Returns -1 if no more bits are set.
     156                 :            :  *
     157                 :            :  * We never touch bytes we don't need to.
     158                 :            :  * On big-endian, array is assumed to consist of
     159                 :            :  * current_wordsize wide words: for example, is current_wordsize is 4,
     160                 :            :  * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
     161                 :            :  * On little-endian machines, word size is immaterial.
     162                 :            :  */
     163                 :            : int
     164                 :        578 : next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
     165                 :            : {
     166                 :        578 :         const unsigned endian = 1;
     167                 :        578 :         int little_endian = *(char *) (void *) &endian;
     168                 :            : 
     169                 :        578 :         const uint8_t *array = bit_array;
     170                 :        578 :         unsigned pos = cur_bit / 8;
     171                 :       2912 :         unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
     172                 :            : 
     173                 :            :         for (;;) {
     174                 :            :                 uint8_t bitmask;
     175                 :            :                 uint8_t cur_byte;
     176                 :            : 
     177         [ +  + ]:       2912 :                 if (cur_bit >= size_bits)
     178                 :            :                         return -1;
     179                 :       2707 :                 cur_byte = array[pos ^ pos_xor_mask];
     180         [ +  + ]:       2707 :                 if (cur_byte == 0) {
     181                 :       2167 :                         cur_bit = (cur_bit + 8) & (-8);
     182                 :       2167 :                         pos++;
     183                 :       2167 :                         continue;
     184                 :            :                 }
     185                 :        540 :                 bitmask = 1 << (cur_bit & 7);
     186                 :            :                 for (;;) {
     187         [ +  + ]:       1646 :                         if (cur_byte & bitmask)
     188                 :        367 :                                 return cur_bit;
     189                 :       1279 :                         cur_bit++;
     190         [ +  + ]:       1279 :                         if (cur_bit >= size_bits)
     191                 :            :                                 return -1;
     192                 :       1273 :                         bitmask <<= 1;
     193                 :            :                         /* This check *can't be* optimized out: */
     194         [ +  + ]:       1273 :                         if (bitmask == 0)
     195                 :            :                                 break;
     196                 :            :                 }
     197                 :        167 :                 pos++;
     198                 :            :         }
     199                 :            : }
     200                 :            : 
     201                 :            : /*
     202                 :            :  * Fetch 64bit argument at position arg_no and
     203                 :            :  * return the index of the next argument.
     204                 :            :  */
     205                 :            : int
     206                 :       1154 : getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
     207                 :            : {
     208                 :            : #if SIZEOF_KERNEL_LONG_T > 4
     209                 :            : # ifndef current_klongsize
     210 [ +  + ][ +  + ]:       1720 :         if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
     211                 :            : #  if defined(AARCH64) || defined(POWERPC64)
     212                 :            :                 /* Align arg_no to the next even number. */
     213                 :            :                 arg_no = (arg_no + 1) & 0xe;
     214                 :            : #  endif /* AARCH64 || POWERPC64 */
     215                 :        862 :                 *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
     216                 :        862 :                 arg_no += 2;
     217                 :            :         } else
     218                 :            : # endif /* !current_klongsize */
     219                 :            :         {
     220                 :        858 :                 *val = tcp->u_arg[arg_no];
     221                 :        858 :                 arg_no++;
     222                 :            :         }
     223                 :            : #else /* SIZEOF_KERNEL_LONG_T == 4 */
     224                 :            : # if defined __ARM_EABI__       \
     225                 :            :   || defined LINUX_MIPSO32      \
     226                 :            :   || defined POWERPC            \
     227                 :            :   || defined XTENSA
     228                 :            :         /* Align arg_no to the next even number. */
     229                 :            :         arg_no = (arg_no + 1) & 0xe;
     230                 :            : # elif defined SH
     231                 :            :         /*
     232                 :            :          * The SH4 ABI does allow long longs in odd-numbered registers, but
     233                 :            :          * does not allow them to be split between registers and memory - and
     234                 :            :          * there are only four argument registers for normal functions.  As a
     235                 :            :          * result, pread, for example, takes an extra padding argument before
     236                 :            :          * the offset.  This was changed late in the 2.4 series (around 2.4.20).
     237                 :            :          */
     238                 :            :         if (arg_no == 3)
     239                 :            :                 arg_no++;
     240                 :            : # endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
     241                 :            :         *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
     242                 :            :         arg_no += 2;
     243                 :            : #endif
     244                 :            : 
     245                 :       1154 :         return arg_no;
     246                 :            : }
     247                 :            : 
     248                 :            : /*
     249                 :            :  * Print 64bit argument at position arg_no and
     250                 :            :  * return the index of the next argument.
     251                 :            :  */
     252                 :            : int
     253                 :        566 : printllval(struct tcb *tcp, const char *format, int arg_no)
     254                 :            : {
     255                 :        566 :         unsigned long long val = 0;
     256                 :            : 
     257                 :        566 :         arg_no = getllval(tcp, &val, arg_no);
     258                 :        566 :         tprintf(format, val);
     259                 :        566 :         return arg_no;
     260                 :            : }
     261                 :            : 
     262                 :            : void
     263                 :     118608 : printaddr(const kernel_ulong_t addr)
     264                 :            : {
     265         [ +  + ]:     118608 :         if (!addr)
     266                 :      69909 :                 tprints("NULL");
     267                 :            :         else
     268                 :      48699 :                 tprintf("%#" PRI_klx, addr);
     269                 :     118608 : }
     270                 :            : 
     271                 :            : #define DEF_PRINTNUM(name, type) \
     272                 :            : bool                                                                    \
     273                 :            : printnum_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,     \
     274                 :            :                   const char *const fmt)                                \
     275                 :            : {                                                                       \
     276                 :            :         type num;                                                       \
     277                 :            :         if (umove_or_printaddr(tcp, addr, &num))                    \
     278                 :            :                 return false;                                           \
     279                 :            :         tprints("[");                                                 \
     280                 :            :         tprintf(fmt, num);                                              \
     281                 :            :         tprints("]");                                                 \
     282                 :            :         return true;                                                    \
     283                 :            : }
     284                 :            : 
     285                 :            : #define DEF_PRINTNUM_ADDR(name, type) \
     286                 :            : bool                                                                    \
     287                 :            : printnum_addr_ ## name(struct tcb *tcp, const kernel_ulong_t addr)      \
     288                 :            : {                                                                       \
     289                 :            :         type num;                                                       \
     290                 :            :         if (umove_or_printaddr(tcp, addr, &num))                    \
     291                 :            :                 return false;                                           \
     292                 :            :         tprints("[");                                                 \
     293                 :            :         printaddr(num);                                                 \
     294                 :            :         tprints("]");                                                 \
     295                 :            :         return true;                                                    \
     296                 :            : }
     297                 :            : 
     298                 :            : #define DEF_PRINTPAIR(name, type) \
     299                 :            : bool                                                                    \
     300                 :            : printpair_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,    \
     301                 :            :                    const char *const fmt)                               \
     302                 :            : {                                                                       \
     303                 :            :         type pair[2];                                                   \
     304                 :            :         if (umove_or_printaddr(tcp, addr, &pair))                   \
     305                 :            :                 return false;                                           \
     306                 :            :         tprints("[");                                                 \
     307                 :            :         tprintf(fmt, pair[0]);                                          \
     308                 :            :         tprints(", ");                                                        \
     309                 :            :         tprintf(fmt, pair[1]);                                          \
     310                 :            :         tprints("]");                                                 \
     311                 :            :         return true;                                                    \
     312                 :            : }
     313                 :            : 
     314         [ +  + ]:       2142 : DEF_PRINTNUM(int, int)
     315         [ +  + ]:         38 : DEF_PRINTNUM_ADDR(int, unsigned int)
     316         [ -  + ]:         16 : DEF_PRINTPAIR(int, int)
     317         [ -  + ]:         12 : DEF_PRINTNUM(short, short)
     318         [ +  + ]:        162 : DEF_PRINTNUM(int64, uint64_t)
     319         [ +  + ]:         24 : DEF_PRINTNUM_ADDR(int64, uint64_t)
     320         [ +  + ]:         24 : DEF_PRINTPAIR(int64, uint64_t)
     321                 :            : 
     322                 :            : #ifndef current_wordsize
     323                 :            : bool
     324                 :         37 : printnum_long_int(struct tcb *const tcp, const kernel_ulong_t addr,
     325                 :            :                   const char *const fmt_long, const char *const fmt_int)
     326                 :            : {
     327         [ +  + ]:         37 :         if (current_wordsize > sizeof(int)) {
     328                 :         14 :                 return printnum_int64(tcp, addr, fmt_long);
     329                 :            :         } else {
     330                 :         23 :                 return printnum_int(tcp, addr, fmt_int);
     331                 :            :         }
     332                 :            : }
     333                 :            : 
     334                 :            : bool
     335                 :         23 : printnum_addr_long_int(struct tcb *tcp, const kernel_ulong_t addr)
     336                 :            : {
     337         [ +  + ]:         23 :         if (current_wordsize > sizeof(int)) {
     338                 :          8 :                 return printnum_addr_int64(tcp, addr);
     339                 :            :         } else {
     340                 :         15 :                 return printnum_addr_int(tcp, addr);
     341                 :            :         }
     342                 :            : }
     343                 :            : #endif /* !current_wordsize */
     344                 :            : 
     345                 :            : #ifndef current_klongsize
     346                 :            : bool
     347                 :          8 : printnum_addr_klong_int(struct tcb *tcp, const kernel_ulong_t addr)
     348                 :            : {
     349         [ +  + ]:          8 :         if (current_klongsize > sizeof(int)) {
     350                 :          4 :                 return printnum_addr_int64(tcp, addr);
     351                 :            :         } else {
     352                 :          4 :                 return printnum_addr_int(tcp, addr);
     353                 :            :         }
     354                 :            : }
     355                 :            : #endif /* !current_klongsize */
     356                 :            : 
     357                 :            : /**
     358                 :            :  * Prints time to a (static internal) buffer and returns pointer to it.
     359                 :            :  *
     360                 :            :  * @param sec           Seconds since epoch.
     361                 :            :  * @param part_sec      Amount of second parts since the start of a second.
     362                 :            :  * @param max_part_sec  Maximum value of a valid part_sec.
     363                 :            :  * @param width         1 + floor(log10(max_part_sec)).
     364                 :            :  */
     365                 :            : static const char *
     366                 :        242 : sprinttime_ex(const long long sec, const unsigned long long part_sec,
     367                 :            :               const unsigned int max_part_sec, const int width)
     368                 :            : {
     369                 :            :         static char buf[sizeof(int) * 3 * 6 + sizeof(part_sec) * 3
     370                 :            :                         + sizeof("+0000")];
     371                 :            : 
     372 [ +  + ][ +  + ]:        242 :         if ((sec == 0 && part_sec == 0) || part_sec > max_part_sec)
     373                 :            :                 return NULL;
     374                 :            : 
     375                 :        216 :         time_t t = (time_t) sec;
     376                 :        216 :         struct tm *tmp = (sec == t) ? localtime(&t) : NULL;
     377         [ +  + ]:        216 :         if (!tmp)
     378                 :            :                 return NULL;
     379                 :            : 
     380                 :        215 :         size_t pos = strftime(buf, sizeof(buf), "%FT%T", tmp);
     381         [ +  - ]:        215 :         if (!pos)
     382                 :            :                 return NULL;
     383                 :            : 
     384         [ +  + ]:        215 :         if (part_sec > 0) {
     385                 :        191 :                 int ret = snprintf(buf + pos, sizeof(buf) - pos, ".%0*llu",
     386                 :            :                                    width, part_sec);
     387                 :            : 
     388 [ +  - ][ +  - ]:        191 :                 if (ret < 0 || (size_t) ret >= sizeof(buf) - pos)
     389                 :            :                         return NULL;
     390                 :            : 
     391                 :        191 :                 pos += ret;
     392                 :            :         }
     393                 :            : 
     394         [ -  + ]:        215 :         return strftime(buf + pos, sizeof(buf) - pos, "%z", tmp) ? buf : NULL;
     395                 :            : }
     396                 :            : 
     397                 :            : const char *
     398                 :         10 : sprinttime(long long sec)
     399                 :            : {
     400                 :         10 :         return sprinttime_ex(sec, 0, 0, 0);
     401                 :            : }
     402                 :            : 
     403                 :            : const char *
     404                 :         24 : sprinttime_usec(long long sec, unsigned long long usec)
     405                 :            : {
     406                 :         24 :         return sprinttime_ex(sec, usec, 999999, 6);
     407                 :            : }
     408                 :            : 
     409                 :            : const char *
     410                 :        208 : sprinttime_nsec(long long sec, unsigned long long nsec)
     411                 :            : {
     412                 :        208 :         return sprinttime_ex(sec, nsec, 999999999, 9);
     413                 :            : }
     414                 :            : 
     415                 :            : enum sock_proto
     416                 :        508 : getfdproto(struct tcb *tcp, int fd)
     417                 :            : {
     418                 :            : #ifdef HAVE_SYS_XATTR_H
     419                 :        508 :         size_t bufsize = 256;
     420                 :        508 :         char buf[bufsize];
     421                 :            :         ssize_t r;
     422                 :            :         char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
     423                 :            : 
     424         [ +  - ]:        508 :         if (fd < 0)
     425                 :            :                 return SOCK_PROTO_UNKNOWN;
     426                 :            : 
     427                 :        508 :         sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
     428                 :        508 :         r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
     429         [ +  - ]:        508 :         if (r <= 0)
     430                 :            :                 return SOCK_PROTO_UNKNOWN;
     431                 :            :         else {
     432                 :            :                 /*
     433                 :            :                  * This is a protection for the case when the kernel
     434                 :            :                  * side does not append a null byte to the buffer.
     435                 :            :                  */
     436                 :        508 :                 buf[r] = '\0';
     437                 :            : 
     438                 :        508 :                 return get_proto_by_name(buf);
     439                 :            :         }
     440                 :            : #else
     441                 :            :         return SOCK_PROTO_UNKNOWN;
     442                 :            : #endif
     443                 :            : }
     444                 :            : 
     445                 :            : unsigned long
     446                 :        346 : getfdinode(struct tcb *tcp, int fd)
     447                 :            : {
     448                 :            :         char path[PATH_MAX + 1];
     449                 :            : 
     450         [ +  - ]:        346 :         if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
     451                 :        346 :                 const char *str = STR_STRIP_PREFIX(path, "socket:[");
     452                 :            : 
     453         [ +  - ]:        346 :                 if (str != path) {
     454                 :        346 :                         const size_t str_len = strlen(str);
     455 [ +  - ][ +  - ]:        346 :                         if (str_len && str[str_len - 1] == ']')
     456                 :        346 :                                 return strtoul(str, NULL, 10);
     457                 :            :                 }
     458                 :            :         }
     459                 :            : 
     460                 :            :         return 0;
     461                 :            : }
     462                 :            : 
     463                 :            : void
     464                 :     511210 : printfd(struct tcb *tcp, int fd)
     465                 :            : {
     466                 :            :         char path[PATH_MAX + 1];
     467 [ +  + ][ +  - ]:     511396 :         if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
     468                 :            :                 const char *str;
     469                 :            :                 size_t len;
     470                 :            :                 unsigned long inode;
     471                 :            : 
     472                 :        186 :                 tprintf("%d<", fd);
     473         [ +  + ]:        186 :                 if (show_fd_path <= 1
     474         [ +  + ]:        106 :                     || (str = STR_STRIP_PREFIX(path, "socket:[")) == path
     475         [ +  - ]:         94 :                     || !(len = strlen(str))
     476         [ +  - ]:         94 :                     || str[len - 1] != ']'
     477         [ +  - ]:         94 :                     || !(inode = strtoul(str, NULL, 10))
     478         [ -  + ]:         94 :                     || !print_sockaddr_by_inode(tcp, fd, inode)) {
     479                 :         92 :                         print_quoted_string(path, strlen(path),
     480                 :            :                                             QUOTE_OMIT_LEADING_TRAILING_QUOTES);
     481                 :            :                 }
     482                 :        186 :                 tprints(">");
     483                 :            :         } else
     484                 :     511024 :                 tprintf("%d", fd);
     485                 :     511210 : }
     486                 :            : 
     487                 :            : /*
     488                 :            :  * Quote string `instr' of length `size'
     489                 :            :  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
     490                 :            :  *
     491                 :            :  * If QUOTE_0_TERMINATED `style' flag is set,
     492                 :            :  * treat `instr' as a NUL-terminated string,
     493                 :            :  * checking up to (`size' + 1) bytes of `instr'.
     494                 :            :  *
     495                 :            :  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
     496                 :            :  * do not add leading and trailing quoting symbols.
     497                 :            :  *
     498                 :            :  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
     499                 :            :  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
     500                 :            :  */
     501                 :            : int
     502                 :     251731 : string_quote(const char *instr, char *outstr, const unsigned int size,
     503                 :            :              const unsigned int style)
     504                 :            : {
     505                 :     251731 :         const unsigned char *ustr = (const unsigned char *) instr;
     506                 :     251731 :         char *s = outstr;
     507                 :            :         unsigned int i;
     508                 :            :         int usehex, c, eol;
     509                 :            : 
     510         [ +  + ]:     251731 :         if (style & QUOTE_0_TERMINATED)
     511                 :            :                 eol = '\0';
     512                 :            :         else
     513                 :     241040 :                 eol = 0x100; /* this can never match a char */
     514                 :            : 
     515                 :     251731 :         usehex = 0;
     516 [ +  + ][ +  + ]:     251731 :         if ((xflag > 1) || (style & QUOTE_FORCE_HEX)) {
     517                 :            :                 usehex = 1;
     518         [ +  + ]:     251595 :         } else if (xflag) {
     519                 :            :                 /* Check for presence of symbol which require
     520                 :            :                    to hex-quote the whole string. */
     521         [ +  + ]:       1486 :                 for (i = 0; i < size; ++i) {
     522                 :       1464 :                         c = ustr[i];
     523                 :            :                         /* Check for NUL-terminated string. */
     524         [ +  - ]:       1464 :                         if (c == eol)
     525                 :            :                                 break;
     526                 :            : 
     527                 :            :                         /* Force hex unless c is printable or whitespace */
     528         [ +  + ]:       1464 :                         if (c > 0x7e) {
     529                 :            :                                 usehex = 1;
     530                 :            :                                 break;
     531                 :            :                         }
     532                 :            :                         /* In ASCII isspace is only these chars: "\t\n\v\f\r".
     533                 :            :                          * They happen to have ASCII codes 9,10,11,12,13.
     534                 :            :                          */
     535         [ +  - ]:       1460 :                         if (c < ' ' && (unsigned)(c - 9) >= 5) {
     536                 :            :                                 usehex = 1;
     537                 :            :                                 break;
     538                 :            :                         }
     539                 :            :                 }
     540                 :            :         }
     541                 :            : 
     542         [ +  + ]:     251731 :         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
     543                 :     251639 :                 *s++ = '\"';
     544                 :            : 
     545         [ +  + ]:     251731 :         if (usehex) {
     546                 :            :                 /* Hex-quote the whole string. */
     547         [ +  + ]:       1206 :                 for (i = 0; i < size; ++i) {
     548                 :       1074 :                         c = ustr[i];
     549                 :            :                         /* Check for NUL-terminated string. */
     550         [ +  + ]:       1074 :                         if (c == eol)
     551                 :            :                                 goto asciz_ended;
     552                 :       1066 :                         *s++ = '\\';
     553                 :       1066 :                         *s++ = 'x';
     554                 :       1066 :                         *s++ = "0123456789abcdef"[c >> 4];
     555                 :       1066 :                         *s++ = "0123456789abcdef"[c & 0xf];
     556                 :            :                 }
     557                 :            :         } else {
     558         [ +  + ]:    1453544 :                 for (i = 0; i < size; ++i) {
     559                 :    1209181 :                         c = ustr[i];
     560                 :            :                         /* Check for NUL-terminated string. */
     561         [ +  + ]:    1209181 :                         if (c == eol)
     562                 :            :                                 goto asciz_ended;
     563 [ +  + ][ +  + ]:    1201963 :                         if ((i == (size - 1)) &&
     564         [ +  + ]:         22 :                             (style & QUOTE_OMIT_TRAILING_0) && (c == '\0'))
     565                 :            :                                 goto asciz_ended;
     566   [ +  +  +  +  :    1201953 :                         switch (c) {
                +  +  + ]
     567                 :            :                                 case '\"': case '\\':
     568                 :        888 :                                         *s++ = '\\';
     569                 :        888 :                                         *s++ = c;
     570                 :        888 :                                         break;
     571                 :            :                                 case '\f':
     572                 :         80 :                                         *s++ = '\\';
     573                 :         80 :                                         *s++ = 'f';
     574                 :         80 :                                         break;
     575                 :            :                                 case '\n':
     576                 :       1357 :                                         *s++ = '\\';
     577                 :       1357 :                                         *s++ = 'n';
     578                 :       1357 :                                         break;
     579                 :            :                                 case '\r':
     580                 :         76 :                                         *s++ = '\\';
     581                 :         76 :                                         *s++ = 'r';
     582                 :         76 :                                         break;
     583                 :            :                                 case '\t':
     584                 :         92 :                                         *s++ = '\\';
     585                 :         92 :                                         *s++ = 't';
     586                 :         92 :                                         break;
     587                 :            :                                 case '\v':
     588                 :         84 :                                         *s++ = '\\';
     589                 :         84 :                                         *s++ = 'v';
     590                 :         84 :                                         break;
     591                 :            :                                 default:
     592         [ +  + ]:    1199376 :                                         if (c >= ' ' && c <= 0x7e)
     593                 :    1185528 :                                                 *s++ = c;
     594                 :            :                                         else {
     595                 :            :                                                 /* Print \octal */
     596                 :      13848 :                                                 *s++ = '\\';
     597         [ +  + ]:      13848 :                                                 if (i + 1 < size
     598         [ +  + ]:      13091 :                                                     && ustr[i + 1] >= '0'
     599         [ +  + ]:       1174 :                                                     && ustr[i + 1] <= '9'
     600                 :            :                                                 ) {
     601                 :            :                                                         /* Print \ooo */
     602                 :         11 :                                                         *s++ = '0' + (c >> 6);
     603                 :         11 :                                                         *s++ = '0' + ((c >> 3) & 0x7);
     604                 :            :                                                 } else {
     605                 :            :                                                         /* Print \[[o]o]o */
     606         [ +  + ]:      13837 :                                                         if ((c >> 3) != 0) {
     607         [ +  + ]:       9701 :                                                                 if ((c >> 6) != 0)
     608                 :       1008 :                                                                         *s++ = '0' + (c >> 6);
     609                 :       9701 :                                                                 *s++ = '0' + ((c >> 3) & 0x7);
     610                 :            :                                                         }
     611                 :            :                                                 }
     612                 :      13848 :                                                 *s++ = '0' + (c & 0x7);
     613                 :            :                                         }
     614                 :            :                                         break;
     615                 :            :                         }
     616                 :            :                 }
     617                 :            :         }
     618                 :            : 
     619         [ +  + ]:     244495 :         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
     620                 :     244403 :                 *s++ = '\"';
     621                 :     244495 :         *s = '\0';
     622                 :            : 
     623                 :            :         /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
     624 [ +  + ][ +  + ]:     244495 :         if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
     625                 :            :                 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
     626                 :            :                  * but next char is NUL.
     627                 :            :                  */
     628                 :            :                 return 0;
     629                 :            :         }
     630                 :            : 
     631                 :     243982 :         return 1;
     632                 :            : 
     633                 :            :  asciz_ended:
     634         [ +  - ]:       7236 :         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
     635                 :       7236 :                 *s++ = '\"';
     636                 :       7236 :         *s = '\0';
     637                 :            :         /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
     638                 :       7236 :         return 0;
     639                 :            : }
     640                 :            : 
     641                 :            : #ifndef ALLOCA_CUTOFF
     642                 :            : # define ALLOCA_CUTOFF  4032
     643                 :            : #endif
     644                 :            : #define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
     645                 :            : 
     646                 :            : /*
     647                 :            :  * Quote string `str' of length `size' and print the result.
     648                 :            :  *
     649                 :            :  * If QUOTE_0_TERMINATED `style' flag is set,
     650                 :            :  * treat `str' as a NUL-terminated string and
     651                 :            :  * quote at most (`size' - 1) bytes.
     652                 :            :  *
     653                 :            :  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
     654                 :            :  * do not add leading and trailing quoting symbols.
     655                 :            :  *
     656                 :            :  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
     657                 :            :  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
     658                 :            :  */
     659                 :            : int
     660                 :       6567 : print_quoted_string(const char *str, unsigned int size,
     661                 :            :                     const unsigned int style)
     662                 :            : {
     663                 :            :         char *buf;
     664                 :            :         char *outstr;
     665                 :            :         unsigned int alloc_size;
     666                 :            :         int rc;
     667                 :            : 
     668 [ +  - ][ +  + ]:       6567 :         if (size && style & QUOTE_0_TERMINATED)
     669                 :       4907 :                 --size;
     670                 :            : 
     671                 :       6567 :         alloc_size = 4 * size;
     672         [ -  + ]:       6567 :         if (alloc_size / 4 != size) {
     673                 :          0 :                 error_msg("Out of memory");
     674                 :          0 :                 tprints("???");
     675                 :          0 :                 return -1;
     676                 :            :         }
     677         [ +  + ]:       6567 :         alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
     678                 :            : 
     679         [ +  + ]:       6567 :         if (use_alloca(alloc_size)) {
     680                 :       4968 :                 outstr = alloca(alloc_size);
     681                 :       4968 :                 buf = NULL;
     682                 :            :         } else {
     683                 :       1599 :                 outstr = buf = malloc(alloc_size);
     684         [ -  + ]:       1599 :                 if (!buf) {
     685                 :          0 :                         error_msg("Out of memory");
     686                 :          0 :                         tprints("???");
     687                 :          0 :                         return -1;
     688                 :            :                 }
     689                 :            :         }
     690                 :            : 
     691                 :       6567 :         rc = string_quote(str, outstr, size, style);
     692                 :       6567 :         tprints(outstr);
     693                 :            : 
     694                 :       6567 :         free(buf);
     695                 :       6567 :         return rc;
     696                 :            : }
     697                 :            : 
     698                 :            : /*
     699                 :            :  * Quote a NUL-terminated string `str' of length up to `size' - 1
     700                 :            :  * and print the result.
     701                 :            :  *
     702                 :            :  * Returns 0 if NUL was seen, 1 otherwise.
     703                 :            :  */
     704                 :            : int
     705                 :       2106 : print_quoted_cstring(const char *str, unsigned int size)
     706                 :            : {
     707                 :       2106 :         int unterminated =
     708                 :            :                 print_quoted_string(str, size, QUOTE_0_TERMINATED);
     709                 :            : 
     710         [ +  + ]:       2106 :         if (unterminated)
     711                 :         22 :                 tprints("...");
     712                 :            : 
     713                 :       2106 :         return unterminated;
     714                 :            : }
     715                 :            : 
     716                 :            : /*
     717                 :            :  * Print path string specified by address `addr' and length `n'.
     718                 :            :  * If path length exceeds `n', append `...' to the output.
     719                 :            :  */
     720                 :            : void
     721                 :      11458 : printpathn(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int n)
     722                 :            : {
     723                 :            :         char path[PATH_MAX + 1];
     724                 :            :         int nul_seen;
     725                 :            : 
     726         [ +  + ]:      11458 :         if (!addr) {
     727                 :        584 :                 tprints("NULL");
     728                 :        584 :                 return;
     729                 :            :         }
     730                 :            : 
     731                 :            :         /* Cap path length to the path buffer size */
     732         [ -  + ]:      10874 :         if (n > sizeof(path) - 1)
     733                 :          0 :                 n = sizeof(path) - 1;
     734                 :            : 
     735                 :            :         /* Fetch one byte more to find out whether path length > n. */
     736                 :      10874 :         nul_seen = umovestr(tcp, addr, n + 1, path);
     737         [ +  + ]:      10874 :         if (nul_seen < 0)
     738                 :       9350 :                 printaddr(addr);
     739                 :            :         else {
     740                 :       1524 :                 path[n++] = !nul_seen;
     741                 :      10874 :                 print_quoted_cstring(path, n);
     742                 :            :         }
     743                 :            : }
     744                 :            : 
     745                 :            : void
     746                 :      11453 : printpath(struct tcb *const tcp, const kernel_ulong_t addr)
     747                 :            : {
     748                 :            :         /* Size must correspond to char path[] size in printpathn */
     749                 :      11453 :         printpathn(tcp, addr, PATH_MAX);
     750                 :      11453 : }
     751                 :            : 
     752                 :            : /*
     753                 :            :  * Print string specified by address `addr' and length `len'.
     754                 :            :  * If `user_style' has QUOTE_0_TERMINATED bit set, treat the string
     755                 :            :  * as a NUL-terminated string.
     756                 :            :  * Pass `user_style' on to `string_quote'.
     757                 :            :  * Append `...' to the output if either the string length exceeds `max_strlen',
     758                 :            :  * or QUOTE_0_TERMINATED bit is set and the string length exceeds `len'.
     759                 :            :  */
     760                 :            : void
     761                 :     250018 : printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
     762                 :            :             const kernel_ulong_t len, const unsigned int user_style)
     763                 :            : {
     764                 :            :         static char *str;
     765                 :            :         static char *outstr;
     766                 :            : 
     767                 :            :         unsigned int size;
     768                 :     250018 :         unsigned int style = user_style;
     769                 :            :         int rc;
     770                 :            :         int ellipsis;
     771                 :            : 
     772         [ +  + ]:     250018 :         if (!addr) {
     773                 :       1588 :                 tprints("NULL");
     774                 :       1588 :                 return;
     775                 :            :         }
     776                 :            :         /* Allocate static buffers if they are not allocated yet. */
     777         [ +  + ]:     248430 :         if (!str) {
     778                 :       1335 :                 const unsigned int outstr_size =
     779                 :       1335 :                         4 * max_strlen + /* for quotes and NUL */ 3;
     780                 :            :                 /*
     781                 :            :                  * We can assume that outstr_size / 4 == max_strlen
     782                 :            :                  * since we have a guarantee that max_strlen <= -1U / 4.
     783                 :            :                  */
     784                 :            : 
     785                 :       1335 :                 str = xmalloc(max_strlen + 1);
     786                 :       1335 :                 outstr = xmalloc(outstr_size);
     787                 :            :         }
     788                 :            : 
     789                 :            :         /* Fetch one byte more because string_quote may look one byte ahead. */
     790                 :     248430 :         size = max_strlen + 1;
     791                 :            : 
     792         [ +  + ]:     248430 :         if (size > len)
     793                 :     239383 :                 size = len;
     794         [ +  + ]:     248430 :         if (style & QUOTE_0_TERMINATED)
     795                 :       8472 :                 rc = umovestr(tcp, addr, size, str);
     796                 :            :         else
     797                 :     239958 :                 rc = umoven(tcp, addr, size, str);
     798                 :            : 
     799         [ +  + ]:     248430 :         if (rc < 0) {
     800                 :       3274 :                 printaddr(addr);
     801                 :       3274 :                 return;
     802                 :            :         }
     803                 :            : 
     804         [ +  + ]:     245156 :         if (size > max_strlen)
     805                 :            :                 size = max_strlen;
     806                 :            :         else
     807                 :     239098 :                 str[size] = '\xff';
     808                 :            : 
     809                 :            :         /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
     810                 :            :          * or we were requested to print more than -s NUM chars)...
     811                 :            :          */
     812                 :     245156 :         ellipsis = string_quote(str, outstr, size, style)
     813         [ +  + ]:     240468 :                    && len
     814 [ +  + ][ +  + ]:     485329 :                    && ((style & QUOTE_0_TERMINATED)
     815         [ +  + ]:     244060 :                        || len > max_strlen);
     816                 :            : 
     817                 :     245156 :         tprints(outstr);
     818         [ +  + ]:     245156 :         if (ellipsis)
     819                 :       1424 :                 tprints("...");
     820                 :            : }
     821                 :            : 
     822                 :            : void
     823                 :         88 : dumpiov_upto(struct tcb *const tcp, const int len, const kernel_ulong_t addr,
     824                 :            :              kernel_ulong_t data_size)
     825                 :            : {
     826                 :            : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
     827                 :            :         union {
     828                 :            :                 struct { uint32_t base; uint32_t len; } *iov32;
     829                 :            :                 struct { uint64_t base; uint64_t len; } *iov64;
     830                 :            :         } iovu;
     831                 :            : #define iov iovu.iov64
     832                 :            : #define sizeof_iov \
     833                 :            :         (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
     834                 :            : #define iov_iov_base(i) \
     835                 :            :         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
     836                 :            : #define iov_iov_len(i) \
     837                 :            :         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
     838                 :            : #else
     839                 :            :         struct iovec *iov;
     840                 :            : #define sizeof_iov sizeof(*iov)
     841                 :            : #define iov_iov_base(i) ptr_to_kulong(iov[i].iov_base)
     842                 :            : #define iov_iov_len(i) iov[i].iov_len
     843                 :            : #endif
     844                 :            :         int i;
     845                 :            :         unsigned size;
     846                 :            : 
     847         [ +  + ]:         88 :         size = sizeof_iov * len;
     848                 :            :         /* Assuming no sane program has millions of iovs */
     849         [ +  - ]:         88 :         if ((unsigned)len > 1024*1024 /* insane or negative size? */
     850         [ -  + ]:         88 :             || (iov = malloc(size)) == NULL) {
     851                 :          0 :                 error_msg("Out of memory");
     852                 :         88 :                 return;
     853                 :            :         }
     854         [ +  - ]:         88 :         if (umoven(tcp, addr, size, iov) >= 0) {
     855         [ +  + ]:        204 :                 for (i = 0; i < len; i++) {
     856         [ +  + ]:        138 :                         kernel_ulong_t iov_len = iov_iov_len(i);
     857         [ +  + ]:        138 :                         if (iov_len > data_size)
     858                 :         44 :                                 iov_len = data_size;
     859         [ +  + ]:        138 :                         if (!iov_len)
     860                 :            :                                 break;
     861                 :        116 :                         data_size -= iov_len;
     862                 :            :                         /* include the buffer number to make it easy to
     863                 :            :                          * match up the trace with the source */
     864                 :        116 :                         tprintf(" * %" PRI_klu " bytes in buffer %d\n", iov_len, i);
     865         [ +  + ]:        116 :                         dumpstr(tcp, iov_iov_base(i), iov_len);
     866                 :            :                 }
     867                 :            :         }
     868                 :         88 :         free(iov);
     869                 :            : #undef sizeof_iov
     870                 :            : #undef iov_iov_base
     871                 :            : #undef iov_iov_len
     872                 :            : #undef iov
     873                 :            : }
     874                 :            : 
     875                 :            : void
     876                 :        414 : dumpstr(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
     877                 :            : {
     878                 :            :         static int strsize = -1;
     879                 :            :         static unsigned char *str;
     880                 :            : 
     881                 :            :         char outbuf[
     882                 :            :                 (
     883                 :            :                         (sizeof(
     884                 :            :                         "xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx  "
     885                 :            :                         "1234567890123456") + /*in case I'm off by few:*/ 4)
     886                 :            :                 /*align to 8 to make memset easier:*/ + 7) & -8
     887                 :            :         ];
     888                 :            :         const unsigned char *src;
     889                 :            :         int i;
     890                 :            : 
     891                 :        414 :         memset(outbuf, ' ', sizeof(outbuf));
     892                 :            : 
     893         [ +  + ]:        414 :         if (strsize < len + 16) {
     894                 :        181 :                 free(str);
     895                 :        181 :                 str = malloc(len + 16);
     896         [ -  + ]:        181 :                 if (!str) {
     897                 :          0 :                         strsize = -1;
     898                 :          0 :                         error_msg("Out of memory");
     899                 :          0 :                         return;
     900                 :            :                 }
     901                 :        181 :                 strsize = len + 16;
     902                 :            :         }
     903                 :            : 
     904         [ +  - ]:        414 :         if (umoven(tcp, addr, len, str) < 0)
     905                 :            :                 return;
     906                 :            : 
     907                 :            :         /* Space-pad to 16 bytes */
     908                 :            :         i = len;
     909         [ +  + ]:       3640 :         while (i & 0xf)
     910                 :       3226 :                 str[i++] = ' ';
     911                 :            : 
     912                 :        414 :         i = 0;
     913                 :        414 :         src = str;
     914         [ +  + ]:        958 :         while (i < len) {
     915                 :            :                 char *dst = outbuf;
     916                 :            :                 /* Hex dump */
     917                 :            :                 do {
     918         [ +  + ]:       8704 :                         if (i < len) {
     919                 :       5478 :                                 *dst++ = "0123456789abcdef"[*src >> 4];
     920                 :       5478 :                                 *dst++ = "0123456789abcdef"[*src & 0xf];
     921                 :            :                         } else {
     922                 :       3226 :                                 *dst++ = ' ';
     923                 :       3226 :                                 *dst++ = ' ';
     924                 :            :                         }
     925                 :       8704 :                         dst++; /* space is there by memset */
     926                 :       8704 :                         i++;
     927         [ +  + ]:       8704 :                         if ((i & 7) == 0)
     928                 :       1088 :                                 dst++; /* space is there by memset */
     929                 :       8704 :                         src++;
     930         [ +  + ]:       8704 :                 } while (i & 0xf);
     931                 :            :                 /* ASCII dump */
     932                 :        544 :                 i -= 16;
     933                 :        544 :                 src -= 16;
     934                 :            :                 do {
     935         [ +  + ]:       8704 :                         if (*src >= ' ' && *src < 0x7f)
     936                 :       4192 :                                 *dst++ = *src;
     937                 :            :                         else
     938                 :       4512 :                                 *dst++ = '.';
     939                 :       8704 :                         src++;
     940         [ +  + ]:       8704 :                 } while (++i & 0xf);
     941                 :        544 :                 *dst = '\0';
     942                 :        544 :                 tprintf(" | %05x  %s |\n", i - 16, outbuf);
     943                 :            :         }
     944                 :            : }
     945                 :            : 
     946                 :            : static bool process_vm_readv_not_supported;
     947                 :            : 
     948                 :            : #ifndef HAVE_PROCESS_VM_READV
     949                 :            : /*
     950                 :            :  * Need to do this since process_vm_readv() is not yet available in libc.
     951                 :            :  * When libc is be updated, only "static bool process_vm_readv_not_supported"
     952                 :            :  * line should remain.
     953                 :            :  */
     954                 :            : /* Have to avoid duplicating with the C library headers. */
     955                 :            : static ssize_t strace_process_vm_readv(pid_t pid,
     956                 :            :                  const struct iovec *lvec,
     957                 :            :                  unsigned long liovcnt,
     958                 :            :                  const struct iovec *rvec,
     959                 :            :                  unsigned long riovcnt,
     960                 :            :                  unsigned long flags)
     961                 :            : {
     962                 :            :         return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
     963                 :            : }
     964                 :            : # define process_vm_readv strace_process_vm_readv
     965                 :            : 
     966                 :            : /*
     967                 :            :  * The same goes for process_vm_writev().
     968                 :            :  */
     969                 :            : static ssize_t strace_process_vm_writev(pid_t pid,
     970                 :            :                  const struct iovec *lvec,
     971                 :            :                  unsigned long liovcnt,
     972                 :            :                  const struct iovec *rvec,
     973                 :            :                  unsigned long riovcnt,
     974                 :            :                  unsigned long flags)
     975                 :            : {
     976                 :            :         return syscall(__NR_process_vm_writev, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
     977                 :            : }
     978                 :            : # define process_vm_writev strace_process_vm_writev
     979                 :            : #endif /* !HAVE_PROCESS_VM_READV */
     980                 :            : 
     981                 :            : static ssize_t
     982                 :     858650 : vm_read_mem(const pid_t pid, void *const laddr,
     983                 :            :             const kernel_ulong_t raddr, const size_t len)
     984                 :            : {
     985                 :     858650 :         const unsigned long truncated_raddr = raddr;
     986                 :            : 
     987                 :            :         if (raddr != (kernel_ulong_t) truncated_raddr) {
     988                 :            :                 errno = EIO;
     989                 :            :                 return -1;
     990                 :            :         }
     991                 :            : 
     992                 :     858650 :         const struct iovec local = {
     993                 :            :                 .iov_base = laddr,
     994                 :            :                 .iov_len = len
     995                 :            :         };
     996                 :     858650 :         const struct iovec remote = {
     997                 :     858650 :                 .iov_base = (void *) truncated_raddr,
     998                 :            :                 .iov_len = len
     999                 :            :         };
    1000                 :            : 
    1001                 :     858650 :         return process_vm_readv(pid, &local, 1, &remote, 1, 0);
    1002                 :            : }
    1003                 :            : 
    1004                 :            : static ssize_t
    1005                 :         19 : vm_write_mem(const pid_t pid, const void *const laddr,
    1006                 :            :             const kernel_ulong_t raddr, const size_t len)
    1007                 :            : {
    1008                 :         19 :         const unsigned long truncated_raddr = raddr;
    1009                 :            : 
    1010                 :            :         if (raddr != (kernel_ulong_t) truncated_raddr) {
    1011                 :            :                 errno = EIO;
    1012                 :            :                 return -1;
    1013                 :            :         }
    1014                 :            : 
    1015                 :         19 :         const struct iovec local = {
    1016                 :            :                 .iov_base = (void *) laddr,
    1017                 :            :                 .iov_len = len
    1018                 :            :         };
    1019                 :         19 :         const struct iovec remote = {
    1020                 :         19 :                 .iov_base = (void *) truncated_raddr,
    1021                 :            :                 .iov_len = len
    1022                 :            :         };
    1023                 :            : 
    1024                 :         19 :         return process_vm_writev(pid, &local, 1, &remote, 1, 0);
    1025                 :            : }
    1026                 :            : 
    1027                 :            : /*
    1028                 :            :  * move `len' bytes of data from process `pid'
    1029                 :            :  * at address `addr' to our space at `our_addr'
    1030                 :            :  */
    1031                 :            : int
    1032                 :     828379 : umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len,
    1033                 :            :        void *const our_addr)
    1034                 :            : {
    1035                 :     828379 :         char *laddr = our_addr;
    1036                 :     828379 :         int pid = tcp->pid;
    1037                 :            :         unsigned int n, m, nread;
    1038                 :            :         union {
    1039                 :            :                 long val;
    1040                 :            :                 char x[sizeof(long)];
    1041                 :            :         } u;
    1042                 :            : 
    1043                 :            : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
    1044         [ +  + ]:     828379 :         if (current_wordsize < sizeof(addr)
    1045         [ +  - ]:     499434 :             && (addr & (~(kernel_ulong_t) -1U))) {
    1046                 :            :                 return -1;
    1047                 :            :         }
    1048                 :            : #endif
    1049                 :            : 
    1050         [ +  - ]:     828379 :         if (!process_vm_readv_not_supported) {
    1051                 :     828379 :                 int r = vm_read_mem(pid, laddr, addr, len);
    1052         [ +  + ]:     828379 :                 if ((unsigned int) r == len)
    1053                 :            :                         return 0;
    1054         [ +  + ]:       1591 :                 if (r >= 0) {
    1055                 :        418 :                         error_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
    1056                 :            :                                   (unsigned int) r, len, addr);
    1057                 :        418 :                         return -1;
    1058                 :            :                 }
    1059   [ -  -  -  + ]:       1173 :                 switch (errno) {
    1060                 :            :                         case ENOSYS:
    1061                 :          0 :                                 process_vm_readv_not_supported = 1;
    1062                 :          0 :                                 break;
    1063                 :            :                         case EPERM:
    1064                 :            :                                 /* operation not permitted, try PTRACE_PEEKDATA */
    1065                 :            :                                 break;
    1066                 :            :                         case ESRCH:
    1067                 :            :                                 /* the process is gone */
    1068                 :            :                                 return -1;
    1069                 :            :                         case EFAULT: case EIO:
    1070                 :            :                                 /* address space is inaccessible */
    1071                 :            :                                 return -1;
    1072                 :            :                         default:
    1073                 :            :                                 /* all the rest is strange and should be reported */
    1074                 :          0 :                                 perror_msg("process_vm_readv");
    1075                 :          0 :                                 return -1;
    1076                 :            :                 }
    1077                 :            :         }
    1078                 :            : 
    1079                 :          0 :         nread = 0;
    1080         [ #  # ]:          0 :         if (addr & (sizeof(long) - 1)) {
    1081                 :            :                 /* addr not a multiple of sizeof(long) */
    1082                 :          0 :                 n = addr & (sizeof(long) - 1);      /* residue */
    1083                 :          0 :                 addr &= -sizeof(long);              /* aligned address */
    1084                 :          0 :                 errno = 0;
    1085                 :          0 :                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
    1086 [ #  # ][ #  # ]:          0 :                 switch (errno) {
                 [ #  # ]
    1087                 :            :                         case 0:
    1088                 :            :                                 break;
    1089                 :            :                         case ESRCH: case EINVAL:
    1090                 :            :                                 /* these could be seen if the process is gone */
    1091                 :            :                                 return -1;
    1092                 :            :                         case EFAULT: case EIO: case EPERM:
    1093                 :            :                                 /* address space is inaccessible */
    1094                 :            :                                 return -1;
    1095                 :            :                         default:
    1096                 :            :                                 /* all the rest is strange and should be reported */
    1097                 :          0 :                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
    1098                 :            :                                             pid, addr);
    1099                 :          0 :                                 return -1;
    1100                 :            :                 }
    1101                 :          0 :                 m = MIN(sizeof(long) - n, len);
    1102                 :          0 :                 memcpy(laddr, &u.x[n], m);
    1103                 :          0 :                 addr += sizeof(long);
    1104                 :          0 :                 laddr += m;
    1105                 :          0 :                 nread += m;
    1106                 :          0 :                 len -= m;
    1107                 :            :         }
    1108         [ #  # ]:          0 :         while (len) {
    1109                 :          0 :                 errno = 0;
    1110                 :          0 :                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
    1111 [ #  # ][ #  # ]:          0 :                 switch (errno) {
         [ #  # ][ #  # ]
    1112                 :            :                         case 0:
    1113                 :            :                                 break;
    1114                 :            :                         case ESRCH: case EINVAL:
    1115                 :            :                                 /* these could be seen if the process is gone */
    1116                 :            :                                 return -1;
    1117                 :            :                         case EFAULT: case EIO: case EPERM:
    1118                 :            :                                 /* address space is inaccessible */
    1119         [ #  # ]:          0 :                                 if (nread) {
    1120                 :          0 :                                         perror_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
    1121                 :            :                                                    nread, nread + len, addr - nread);
    1122                 :            :                                 }
    1123                 :            :                                 return -1;
    1124                 :            :                         default:
    1125                 :            :                                 /* all the rest is strange and should be reported */
    1126                 :          0 :                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
    1127                 :            :                                             pid, addr);
    1128                 :          0 :                                 return -1;
    1129                 :            :                 }
    1130                 :          0 :                 m = MIN(sizeof(long), len);
    1131                 :          0 :                 memcpy(laddr, u.x, m);
    1132                 :          0 :                 addr += sizeof(long);
    1133                 :          0 :                 laddr += m;
    1134                 :          0 :                 nread += m;
    1135                 :          0 :                 len -= m;
    1136                 :            :         }
    1137                 :            : 
    1138                 :            :         return 0;
    1139                 :            : }
    1140                 :            : 
    1141                 :            : int
    1142                 :      12004 : umoven_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr,
    1143                 :            :                     const unsigned int len, void *const our_addr)
    1144                 :            : {
    1145 [ +  + ][ +  + ]:      21789 :         if (!addr || !verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
                 [ +  + ]
           [ +  +  +  + ]
    1146                 :       9785 :             umoven(tcp, addr, len, our_addr) < 0) {
    1147                 :       2781 :                 printaddr(addr);
    1148                 :       2781 :                 return -1;
    1149                 :            :         }
    1150                 :            :         return 0;
    1151                 :            : }
    1152                 :            : 
    1153                 :            : int
    1154                 :     238361 : umoven_or_printaddr_ignore_syserror(struct tcb *const tcp,
    1155                 :            :                                     const kernel_ulong_t addr,
    1156                 :            :                                     const unsigned int len,
    1157                 :            :                                     void *const our_addr)
    1158                 :            : {
    1159 [ +  - ][ +  - ]:     238361 :         if (!addr || !verbose(tcp) || umoven(tcp, addr, len, our_addr) < 0) {
                 [ +  + ]
    1160                 :        105 :                 printaddr(addr);
    1161                 :        105 :                 return -1;
    1162                 :            :         }
    1163                 :            :         return 0;
    1164                 :            : }
    1165                 :            : 
    1166                 :            : /*
    1167                 :            :  * Like `umove' but make the additional effort of looking
    1168                 :            :  * for a terminating zero byte.
    1169                 :            :  *
    1170                 :            :  * Returns < 0 on error, > 0 if NUL was seen,
    1171                 :            :  * (TODO if useful: return count of bytes including NUL),
    1172                 :            :  * else 0 if len bytes were read but no NUL byte seen.
    1173                 :            :  *
    1174                 :            :  * Note: there is no guarantee we won't overwrite some bytes
    1175                 :            :  * in laddr[] _after_ terminating NUL (but, of course,
    1176                 :            :  * we never write past laddr[len-1]).
    1177                 :            :  */
    1178                 :            : int
    1179                 :      20161 : umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *laddr)
    1180                 :            : {
    1181                 :      20161 :         const unsigned long x01010101 = (unsigned long) 0x0101010101010101ULL;
    1182                 :      20161 :         const unsigned long x80808080 = (unsigned long) 0x8080808080808080ULL;
    1183                 :            : 
    1184                 :      20161 :         int pid = tcp->pid;
    1185                 :            :         unsigned int n, m, nread;
    1186                 :            :         union {
    1187                 :            :                 unsigned long val;
    1188                 :            :                 char x[sizeof(long)];
    1189                 :            :         } u;
    1190                 :            : 
    1191                 :            : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
    1192         [ +  + ]:      20161 :         if (current_wordsize < sizeof(addr)
    1193         [ +  - ]:       9097 :             && (addr & (~(kernel_ulong_t) -1U))) {
    1194                 :            :                 return -1;
    1195                 :            :         }
    1196                 :            : #endif
    1197                 :            : 
    1198                 :      20161 :         nread = 0;
    1199         [ +  - ]:      20161 :         if (!process_vm_readv_not_supported) {
    1200                 :      20161 :                 const size_t page_size = get_pagesize();
    1201                 :      20161 :                 const size_t page_mask = page_size - 1;
    1202                 :            : 
    1203         [ +  + ]:      31369 :                 while (len > 0) {
    1204                 :            :                         unsigned int chunk_len;
    1205                 :            :                         unsigned int end_in_page;
    1206                 :            : 
    1207                 :            :                         /*
    1208                 :            :                          * Don't cross pages, otherwise we can get EFAULT
    1209                 :            :                          * and fail to notice that terminating NUL lies
    1210                 :            :                          * in the existing (first) page.
    1211                 :            :                          */
    1212                 :      30271 :                         chunk_len = len > page_size ? page_size : len;
    1213                 :      30271 :                         end_in_page = (addr + chunk_len) & page_mask;
    1214         [ +  + ]:      30271 :                         if (chunk_len > end_in_page) /* crosses to the next page */
    1215                 :      13984 :                                 chunk_len -= end_in_page;
    1216                 :            : 
    1217                 :      30271 :                         int r = vm_read_mem(pid, laddr, addr, chunk_len);
    1218         [ +  + ]:      30271 :                         if (r > 0) {
    1219         [ +  + ]:      18225 :                                 if (memchr(laddr, '\0', r))
    1220                 :            :                                         return 1;
    1221                 :      11208 :                                 addr += r;
    1222                 :      11208 :                                 laddr += r;
    1223                 :      11208 :                                 nread += r;
    1224                 :      11208 :                                 len -= r;
    1225                 :      11208 :                                 continue;
    1226                 :            :                         }
    1227   [ -  -  +  -  :      12046 :                         switch (errno) {
                      - ]
    1228                 :            :                                 case ENOSYS:
    1229                 :          0 :                                         process_vm_readv_not_supported = 1;
    1230                 :          0 :                                         goto vm_readv_didnt_work;
    1231                 :            :                                 case ESRCH:
    1232                 :            :                                         /* the process is gone */
    1233                 :            :                                         return -1;
    1234                 :            :                                 case EPERM:
    1235                 :            :                                         /* operation not permitted, try PTRACE_PEEKDATA */
    1236         [ #  # ]:          0 :                                         if (!nread)
    1237                 :            :                                                 goto vm_readv_didnt_work;
    1238                 :            :                                         /* fall through */
    1239                 :            :                                 case EFAULT: case EIO:
    1240                 :            :                                         /* address space is inaccessible */
    1241         [ +  + ]:      12046 :                                         if (nread) {
    1242                 :      10102 :                                                 perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
    1243                 :            :                                                            nread, nread + len, addr - nread);
    1244                 :            :                                         }
    1245                 :            :                                         return -1;
    1246                 :            :                                 default:
    1247                 :            :                                         /* all the rest is strange and should be reported */
    1248                 :          0 :                                         perror_msg("process_vm_readv");
    1249                 :          0 :                                         return -1;
    1250                 :            :                         }
    1251                 :            :                 }
    1252                 :            :                 return 0;
    1253                 :            :         }
    1254                 :            :  vm_readv_didnt_work:
    1255                 :            : 
    1256         [ #  # ]:          0 :         if (addr & (sizeof(long) - 1)) {
    1257                 :            :                 /* addr not a multiple of sizeof(long) */
    1258                 :          0 :                 n = addr & (sizeof(long) - 1);      /* residue */
    1259                 :          0 :                 addr &= -sizeof(long);              /* aligned address */
    1260                 :          0 :                 errno = 0;
    1261                 :          0 :                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
    1262 [ #  # ][ #  # ]:          0 :                 switch (errno) {
                 [ #  # ]
    1263                 :            :                         case 0:
    1264                 :            :                                 break;
    1265                 :            :                         case ESRCH: case EINVAL:
    1266                 :            :                                 /* these could be seen if the process is gone */
    1267                 :            :                                 return -1;
    1268                 :            :                         case EFAULT: case EIO: case EPERM:
    1269                 :            :                                 /* address space is inaccessible */
    1270                 :            :                                 return -1;
    1271                 :            :                         default:
    1272                 :            :                                 /* all the rest is strange and should be reported */
    1273                 :          0 :                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
    1274                 :            :                                             pid, addr);
    1275                 :          0 :                                 return -1;
    1276                 :            :                 }
    1277                 :          0 :                 m = MIN(sizeof(long) - n, len);
    1278                 :          0 :                 memcpy(laddr, &u.x[n], m);
    1279         [ #  # ]:          0 :                 while (n & (sizeof(long) - 1))
    1280         [ #  # ]:          0 :                         if (u.x[n++] == '\0')
    1281                 :            :                                 return 1;
    1282                 :          0 :                 addr += sizeof(long);
    1283                 :          0 :                 laddr += m;
    1284                 :          0 :                 nread += m;
    1285                 :          0 :                 len -= m;
    1286                 :            :         }
    1287                 :            : 
    1288         [ #  # ]:          0 :         while (len) {
    1289                 :          0 :                 errno = 0;
    1290                 :          0 :                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
    1291 [ #  # ][ #  # ]:          0 :                 switch (errno) {
         [ #  # ][ #  # ]
    1292                 :            :                         case 0:
    1293                 :            :                                 break;
    1294                 :            :                         case ESRCH: case EINVAL:
    1295                 :            :                                 /* these could be seen if the process is gone */
    1296                 :            :                                 return -1;
    1297                 :            :                         case EFAULT: case EIO: case EPERM:
    1298                 :            :                                 /* address space is inaccessible */
    1299         [ #  # ]:          0 :                                 if (nread) {
    1300                 :          0 :                                         perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
    1301                 :            :                                                    nread, nread + len, addr - nread);
    1302                 :            :                                 }
    1303                 :            :                                 return -1;
    1304                 :            :                         default:
    1305                 :            :                                 /* all the rest is strange and should be reported */
    1306                 :          0 :                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
    1307                 :            :                                            pid, addr);
    1308                 :          0 :                                 return -1;
    1309                 :            :                 }
    1310                 :          0 :                 m = MIN(sizeof(long), len);
    1311                 :          0 :                 memcpy(laddr, u.x, m);
    1312                 :            :                 /* "If a NUL char exists in this word" */
    1313         [ #  # ]:          0 :                 if ((u.val - x01010101) & ~u.val & x80808080)
    1314                 :            :                         return 1;
    1315                 :          0 :                 addr += sizeof(long);
    1316                 :          0 :                 laddr += m;
    1317                 :          0 :                 nread += m;
    1318                 :          0 :                 len -= m;
    1319                 :            :         }
    1320                 :            :         return 0;
    1321                 :            : }
    1322                 :            : 
    1323                 :            : static bool
    1324                 :          0 : partial_poke(int pid, kernel_ulong_t addr, unsigned int len, const void *laddr,
    1325                 :            :              unsigned int off)
    1326                 :            : {
    1327                 :            :         union {
    1328                 :            :                 long val;
    1329                 :            :                 char x[sizeof(long)];
    1330                 :            :         } u;
    1331                 :          0 :         errno = 0;
    1332                 :          0 :         u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
    1333 [ #  # ][ #  # ]:          0 :         switch (errno) {
                 [ #  # ]
    1334                 :            :                 case 0:
    1335                 :            :                         break;
    1336                 :            :                 case ESRCH: case EINVAL:
    1337                 :            :                         /* these could be seen if the process is gone */
    1338                 :            :                         return false;
    1339                 :            :                 case EFAULT: case EIO: case EPERM:
    1340                 :            :                         /* address space is inaccessible */
    1341                 :            :                         return false;
    1342                 :            :                 default:
    1343                 :            :                         /* all the rest is strange and should be reported */
    1344                 :          0 :                         perror_msg("partial_poke: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
    1345                 :            :                                     pid, addr);
    1346                 :          0 :                         return false;
    1347                 :            :         }
    1348                 :            : 
    1349                 :          0 :         memcpy(u.x + off, laddr, len);
    1350                 :            : 
    1351                 :            :         /* now write it back */
    1352         [ #  # ]:          0 :         if (ptrace(PTRACE_POKEDATA, pid, addr, u.val) < 0) {
    1353 [ #  # ][ #  # ]:          0 :                 switch (errno) {
    1354                 :            :                         case ESRCH: case EINVAL:
    1355                 :            :                                 /* these could be seen if the process is gone */
    1356                 :            :                                 return -1;
    1357                 :            :                         case EFAULT: case EIO: case EPERM:
    1358                 :            :                                 /* address space is inaccessible, or write is prohibited */
    1359                 :            :                                 return -1;
    1360                 :            :                         default:
    1361                 :            :                                 /* all the rest is strange and should be reported */
    1362                 :          0 :                                 perror_msg("partial_poke: PTRACE_POKEDATA pid:%d @0x%" PRI_klx,
    1363                 :            :                                             pid, addr);
    1364                 :          0 :                                 return -1;
    1365                 :            :                 }
    1366                 :            :         }
    1367                 :            : 
    1368                 :            :         return true;
    1369                 :            : }
    1370                 :            : 
    1371                 :            : int
    1372                 :         20 : upoken(struct tcb *tcp, kernel_ulong_t addr, unsigned int len,
    1373                 :            :        const void *const our_addr)
    1374                 :            : {
    1375         [ +  + ]:         20 :         if (!len)
    1376                 :            :                 return 0;
    1377                 :            : 
    1378                 :         19 :         const char *laddr = our_addr;
    1379                 :         19 :         int pid = tcp->pid;
    1380                 :            : 
    1381                 :            : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
    1382         [ -  + ]:         19 :         if (current_wordsize < sizeof(addr)
    1383         [ #  # ]:          0 :             && (addr & (~(kernel_ulong_t) -1U))) {
    1384                 :            :                 return -1;
    1385                 :            :         }
    1386                 :            : #endif
    1387                 :            : 
    1388         [ +  - ]:         19 :         if (!process_vm_readv_not_supported) {
    1389                 :         19 :                 int r = vm_write_mem(pid, laddr, addr, len);
    1390         [ -  + ]:         19 :                 if ((unsigned int) r == len)
    1391                 :            :                         return 0;
    1392         [ #  # ]:          0 :                 if (r >= 0) {
    1393                 :          0 :                         error_msg("upoken: short write (%u < %u) @0x%" PRI_klx,
    1394                 :            :                                   (unsigned int) r, len, addr);
    1395                 :          0 :                         return -1;
    1396                 :            :                 }
    1397   [ #  #  #  # ]:          0 :                 switch (errno) {
    1398                 :            :                         case ENOSYS:
    1399                 :          0 :                                 process_vm_readv_not_supported = 1;
    1400                 :          0 :                                 break;
    1401                 :            :                         case EPERM:
    1402                 :            :                                 /* operation not permitted, try PTRACE_POKEDATA */
    1403                 :            :                                 break;
    1404                 :            :                         case ESRCH:
    1405                 :            :                                 /* the process is gone */
    1406                 :            :                                 return -1;
    1407                 :            :                         case EFAULT: case EIO:
    1408                 :            :                                 /* address space is inaccessible */
    1409                 :            :                                 return -1;
    1410                 :            :                         default:
    1411                 :            :                                 /* all the rest is strange and should be reported */
    1412                 :          0 :                                 perror_msg("process_vm_writev");
    1413                 :          0 :                                 return -1;
    1414                 :            :                 }
    1415                 :            :         }
    1416                 :            : 
    1417         [ #  # ]:          0 :         if (addr & (sizeof(long) - 1)) {
    1418                 :            :                 /* addr not a multiple of sizeof(long) */
    1419                 :          0 :                 unsigned n = addr & (sizeof(long) - 1);     /* residue */
    1420                 :          0 :                 addr &= -sizeof(long);                      /* aligned address */
    1421                 :          0 :                 unsigned m = MIN(sizeof(long) - n, len);
    1422         [ #  # ]:          0 :                 if (!partial_poke(pid, addr, m, laddr, n))
    1423                 :            :                         return -1;
    1424                 :          0 :                 addr += sizeof(long);
    1425                 :          0 :                 laddr += m;
    1426                 :          0 :                 len -= m;
    1427                 :            :         }
    1428                 :            : 
    1429         [ #  # ]:          0 :         while (len >= sizeof(long)) {
    1430         [ #  # ]:          0 :                 if (ptrace(PTRACE_POKEDATA, pid, addr, * (const long *) laddr) < 0) {
    1431 [ #  # ][ #  # ]:          0 :                         switch (errno) {
    1432                 :            :                         case ESRCH: case EINVAL:
    1433                 :            :                                 /* these could be seen if the process is gone */
    1434                 :            :                                 return -1;
    1435                 :            :                         case EFAULT: case EIO: case EPERM:
    1436                 :            :                                 /* address space is inaccessible, or write is prohibited */
    1437                 :            :                                 return -1;
    1438                 :            :                         default:
    1439                 :            :                                 /* all the rest is strange and should be reported */
    1440                 :          0 :                                 perror_msg("upoken: PTRACE_POKEDATA pid:%d @0x%" PRI_klx,
    1441                 :            :                                             pid, addr);
    1442                 :          0 :                                 return -1;
    1443                 :            :                         }
    1444                 :            :                 }
    1445                 :          0 :                 addr += sizeof(long);
    1446                 :          0 :                 laddr += sizeof(long);
    1447                 :          0 :                 len -= sizeof(long);
    1448                 :            :         }
    1449                 :            : 
    1450         [ #  # ]:          0 :         if (len) {
    1451         [ #  # ]:          0 :                 if (!partial_poke(pid, addr, len, laddr, 0))
    1452                 :            :                         return -1;
    1453                 :            :         }
    1454                 :            : 
    1455                 :            :         return 0;
    1456                 :            : }
    1457                 :            : 
    1458                 :            : /*
    1459                 :            :  * Iteratively fetch and print up to nmemb elements of elem_size size
    1460                 :            :  * from the array that starts at tracee's address start_addr.
    1461                 :            :  *
    1462                 :            :  * Array elements are being fetched to the address specified by elem_buf.
    1463                 :            :  *
    1464                 :            :  * The fetcher callback function specified by umoven_func should follow
    1465                 :            :  * the same semantics as umoven_or_printaddr function.
    1466                 :            :  *
    1467                 :            :  * The printer callback function specified by print_func is expected
    1468                 :            :  * to print something; if it returns false, no more iterations will be made.
    1469                 :            :  *
    1470                 :            :  * The pointer specified by opaque_data is passed to each invocation
    1471                 :            :  * of print_func callback function.
    1472                 :            :  *
    1473                 :            :  * This function prints:
    1474                 :            :  * - "NULL", if start_addr is NULL;
    1475                 :            :  * - "[]", if nmemb is 0;
    1476                 :            :  * - start_addr, if nmemb * elem_size overflows or wraps around;
    1477                 :            :  * - nothing, if the first element cannot be fetched
    1478                 :            :  *   (if umoven_func returns non-zero), but it is assumed that
    1479                 :            :  *   umoven_func has printed the address it failed to fetch data from;
    1480                 :            :  * - elements of the array, delimited by ", ", with the array itself
    1481                 :            :  *   enclosed with [] brackets.
    1482                 :            :  *
    1483                 :            :  * If abbrev(tcp) is true, then
    1484                 :            :  * - the maximum number of elements printed equals to max_strlen;
    1485                 :            :  * - "..." is printed instead of max_strlen+1 element
    1486                 :            :  *   and no more iterations will be made.
    1487                 :            :  *
    1488                 :            :  * This function returns true only if
    1489                 :            :  * - umoven_func has been called at least once AND
    1490                 :            :  * - umoven_func has not returned false.
    1491                 :            :  */
    1492                 :            : bool
    1493                 :     303669 : print_array(struct tcb *const tcp,
    1494                 :            :             const kernel_ulong_t start_addr,
    1495                 :            :             const size_t nmemb,
    1496                 :            :             void *const elem_buf,
    1497                 :            :             const size_t elem_size,
    1498                 :            :             int (*const umoven_func)(struct tcb *,
    1499                 :            :                                      kernel_ulong_t,
    1500                 :            :                                      unsigned int,
    1501                 :            :                                      void *),
    1502                 :            :             bool (*const print_func)(struct tcb *,
    1503                 :            :                                      void *elem_buf,
    1504                 :            :                                      size_t elem_size,
    1505                 :            :                                      void *opaque_data),
    1506                 :            :             void *const opaque_data)
    1507                 :            : {
    1508         [ +  + ]:     303669 :         if (!start_addr) {
    1509                 :      65162 :                 tprints("NULL");
    1510                 :      65162 :                 return false;
    1511                 :            :         }
    1512                 :            : 
    1513         [ +  + ]:     238507 :         if (!nmemb) {
    1514                 :         69 :                 tprints("[]");
    1515                 :         69 :                 return false;
    1516                 :            :         }
    1517                 :            : 
    1518                 :     238438 :         const size_t size = nmemb * elem_size;
    1519                 :     238438 :         const kernel_ulong_t end_addr = start_addr + size;
    1520                 :            : 
    1521 [ +  + ][ +  + ]:     238438 :         if (end_addr <= start_addr || size / elem_size != nmemb) {
    1522                 :         20 :                 printaddr(start_addr);
    1523                 :         20 :                 return false;
    1524                 :            :         }
    1525                 :            : 
    1526                 :     238418 :         const kernel_ulong_t abbrev_end =
    1527         [ +  + ]:     233710 :                 (abbrev(tcp) && max_strlen < nmemb) ?
    1528         [ +  + ]:     238624 :                         start_addr + elem_size * max_strlen : end_addr;
    1529                 :            :         kernel_ulong_t cur;
    1530                 :            : 
    1531         [ +  + ]:     482453 :         for (cur = start_addr; cur < end_addr; cur += elem_size) {
    1532         [ +  + ]:     244406 :                 if (cur != start_addr)
    1533                 :       5988 :                         tprints(", ");
    1534                 :            : 
    1535         [ +  + ]:     244406 :                 if (umoven_func(tcp, cur, elem_size, elem_buf))
    1536                 :            :                         break;
    1537                 :            : 
    1538         [ +  + ]:     244155 :                 if (cur == start_addr)
    1539                 :     238283 :                         tprints("[");
    1540                 :            : 
    1541         [ +  + ]:     244155 :                 if (cur >= abbrev_end) {
    1542                 :        112 :                         tprints("...");
    1543                 :        112 :                         cur = end_addr;
    1544                 :        112 :                         break;
    1545                 :            :                 }
    1546                 :            : 
    1547         [ +  + ]:     244043 :                 if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
    1548                 :            :                         cur = end_addr;
    1549                 :            :                         break;
    1550                 :            :                 }
    1551                 :            :         }
    1552         [ +  + ]:     238418 :         if (cur != start_addr)
    1553                 :     238283 :                 tprints("]");
    1554                 :            : 
    1555                 :     238418 :         return cur >= end_addr;
    1556                 :            : }
    1557                 :            : 
    1558                 :            : int
    1559                 :     120804 : printargs(struct tcb *tcp)
    1560                 :            : {
    1561                 :     120804 :         const int n = tcp->s_ent->nargs;
    1562                 :            :         int i;
    1563         [ +  + ]:     526226 :         for (i = 0; i < n; ++i)
    1564         [ +  + ]:     405422 :                 tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
    1565                 :     120804 :         return RVAL_DECODED;
    1566                 :            : }
    1567                 :            : 
    1568                 :            : int
    1569                 :          2 : printargs_u(struct tcb *tcp)
    1570                 :            : {
    1571                 :          2 :         const int n = tcp->s_ent->nargs;
    1572                 :            :         int i;
    1573         [ +  + ]:          4 :         for (i = 0; i < n; ++i)
    1574         [ +  - ]:          2 :                 tprintf("%s%u", i ? ", " : "",
    1575                 :          2 :                         (unsigned int) tcp->u_arg[i]);
    1576                 :          2 :         return RVAL_DECODED;
    1577                 :            : }
    1578                 :            : 
    1579                 :            : int
    1580                 :         44 : printargs_d(struct tcb *tcp)
    1581                 :            : {
    1582                 :         44 :         const int n = tcp->s_ent->nargs;
    1583                 :            :         int i;
    1584         [ +  + ]:         90 :         for (i = 0; i < n; ++i)
    1585         [ +  + ]:         46 :                 tprintf("%s%d", i ? ", " : "",
    1586                 :         46 :                         (int) tcp->u_arg[i]);
    1587                 :         44 :         return RVAL_DECODED;
    1588                 :            : }
    1589                 :            : 
    1590                 :            : /* Print abnormal high bits of a kernel_ulong_t value. */
    1591                 :            : void
    1592                 :          0 : print_abnormal_hi(const kernel_ulong_t val)
    1593                 :            : {
    1594         [ #  # ]:          0 :         if (current_klongsize > 4) {
    1595                 :          0 :                 const unsigned int hi = (unsigned int) ((uint64_t) val >> 32);
    1596         [ #  # ]:          0 :                 if (hi)
    1597                 :          0 :                         tprintf("%#x<<32|", hi);
    1598                 :            :         }
    1599                 :          0 : }
    1600                 :            : 
    1601                 :            : #if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
    1602                 :            : # define open_file open64
    1603                 :            : #else
    1604                 :            : # define open_file open
    1605                 :            : #endif
    1606                 :            : 
    1607                 :            : int
    1608                 :          8 : read_int_from_file(const char *const fname, int *const pvalue)
    1609                 :            : {
    1610                 :          8 :         const int fd = open_file(fname, O_RDONLY);
    1611         [ +  - ]:          8 :         if (fd < 0)
    1612                 :            :                 return -1;
    1613                 :            : 
    1614                 :            :         long lval;
    1615                 :            :         char buf[sizeof(lval) * 3];
    1616                 :          8 :         int n = read(fd, buf, sizeof(buf) - 1);
    1617                 :          8 :         int saved_errno = errno;
    1618                 :          8 :         close(fd);
    1619                 :            : 
    1620         [ -  + ]:          8 :         if (n < 0) {
    1621                 :          0 :                 errno = saved_errno;
    1622                 :          0 :                 return -1;
    1623                 :            :         }
    1624                 :            : 
    1625                 :          8 :         buf[n] = '\0';
    1626                 :          8 :         char *endptr = 0;
    1627                 :          8 :         errno = 0;
    1628                 :          8 :         lval = strtol(buf, &endptr, 10);
    1629 [ +  - ][ +  - ]:          8 :         if (!endptr || (*endptr && '\n' != *endptr)
    1630                 :            : #if INT_MAX < LONG_MAX
    1631         [ +  - ]:          8 :             || lval > INT_MAX || lval < INT_MIN
    1632                 :            : #endif
    1633         [ -  + ]:          8 :             || ERANGE == errno) {
    1634         [ #  # ]:          0 :                 if (!errno)
    1635                 :          0 :                         errno = EINVAL;
    1636                 :            :                 return -1;
    1637                 :            :         }
    1638                 :            : 
    1639                 :          8 :         *pvalue = (int) lval;
    1640                 :          8 :         return 0;
    1641                 :            : }

Generated by: LCOV version 1.11