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