]> granicus.if.org Git - strace/blob - util.c
ea3488d4afa3dbdd1cb0ab35e3340378349727c0
[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/user.h>
36 #include <sys/param.h>
37 #include <fcntl.h>
38 #if HAVE_SYS_UIO_H
39 # include <sys/uio.h>
40 #endif
41
42 #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
43 # include <linux/ptrace.h>
44 #endif
45
46 #if defined(IA64)
47 # include <asm/ptrace_offsets.h>
48 # include <asm/rse.h>
49 #endif
50
51 #ifdef HAVE_SYS_REG_H
52 # include <sys/reg.h>
53 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
54 #elif defined(HAVE_LINUX_PTRACE_H)
55 # undef PTRACE_SYSCALL
56 # ifdef HAVE_STRUCT_IA64_FPREG
57 #  define ia64_fpreg XXX_ia64_fpreg
58 # endif
59 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
60 #  define pt_all_user_regs XXX_pt_all_user_regs
61 # endif
62 # include <linux/ptrace.h>
63 # undef ia64_fpreg
64 # undef pt_all_user_regs
65 #endif
66
67 #if defined(SPARC64)
68 # undef PTRACE_GETREGS
69 # define PTRACE_GETREGS PTRACE_GETREGS64
70 # undef PTRACE_SETREGS
71 # define PTRACE_SETREGS PTRACE_SETREGS64
72 #endif
73
74 /* macros */
75 #ifndef MAX
76 # define MAX(a,b)               (((a) > (b)) ? (a) : (b))
77 #endif
78 #ifndef MIN
79 # define MIN(a,b)               (((a) < (b)) ? (a) : (b))
80 #endif
81
82 int
83 string_to_uint(const char *str)
84 {
85         char *error;
86         long value;
87
88         if (!*str)
89                 return -1;
90         errno = 0;
91         value = strtol(str, &error, 10);
92         if (errno || *error || value < 0 || (long)(int)value != value)
93                 return -1;
94         return (int)value;
95 }
96
97 int
98 tv_nz(struct timeval *a)
99 {
100         return a->tv_sec || a->tv_usec;
101 }
102
103 int
104 tv_cmp(struct timeval *a, struct timeval *b)
105 {
106         if (a->tv_sec < b->tv_sec
107             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
108                 return -1;
109         if (a->tv_sec > b->tv_sec
110             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
111                 return 1;
112         return 0;
113 }
114
115 double
116 tv_float(struct timeval *tv)
117 {
118         return tv->tv_sec + tv->tv_usec/1000000.0;
119 }
120
121 void
122 tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
123 {
124         tv->tv_sec = a->tv_sec + b->tv_sec;
125         tv->tv_usec = a->tv_usec + b->tv_usec;
126         if (tv->tv_usec >= 1000000) {
127                 tv->tv_sec++;
128                 tv->tv_usec -= 1000000;
129         }
130 }
131
132 void
133 tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
134 {
135         tv->tv_sec = a->tv_sec - b->tv_sec;
136         tv->tv_usec = a->tv_usec - b->tv_usec;
137         if (((long) tv->tv_usec) < 0) {
138                 tv->tv_sec--;
139                 tv->tv_usec += 1000000;
140         }
141 }
142
143 void
144 tv_div(struct timeval *tv, struct timeval *a, int n)
145 {
146         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
147         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
148         tv->tv_usec %= 1000000;
149 }
150
151 void
152 tv_mul(struct timeval *tv, struct timeval *a, int n)
153 {
154         tv->tv_usec = a->tv_usec * n;
155         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
156         tv->tv_usec %= 1000000;
157 }
158
159 const char *
160 xlookup(const struct xlat *xlat, int val)
161 {
162         for (; xlat->str != NULL; xlat++)
163                 if (xlat->val == val)
164                         return xlat->str;
165         return NULL;
166 }
167
168 #if !defined HAVE_STPCPY
169 char *
170 stpcpy(char *dst, const char *src)
171 {
172         while ((*dst = *src++) != '\0')
173                 dst++;
174         return dst;
175 }
176 #endif
177
178 /*
179  * Print entry in struct xlat table, if there.
180  */
181 void
182 printxval(const struct xlat *xlat, int val, const char *dflt)
183 {
184         const char *str = xlookup(xlat, val);
185
186         if (str)
187                 tprints(str);
188         else
189                 tprintf("%#x /* %s */", val, dflt);
190 }
191
192 #if HAVE_LONG_LONG
193 /*
194  * Print 64bit argument at position llarg and return the index of the next
195  * argument.
196  */
197 int
198 printllval(struct tcb *tcp, const char *format, int llarg)
199 {
200 # if defined(X86_64) || defined(POWERPC64)
201         if (current_personality == 0) {
202                 tprintf(format, tcp->u_arg[llarg]);
203                 llarg++;
204         } else {
205 #  ifdef POWERPC64
206                 /* Align 64bit argument to 64bit boundary.  */
207                 llarg = (llarg + 1) & 0x1e;
208 #  endif
209                 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
210                 llarg += 2;
211         }
212 # elif defined IA64 || defined ALPHA
213         tprintf(format, tcp->u_arg[llarg]);
214         llarg++;
215 # elif defined LINUX_MIPSN32
216         tprintf(format, tcp->ext_arg[llarg]);
217         llarg++;
218 # else
219         tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
220         llarg += 2;
221 # endif
222         return llarg;
223 }
224 #endif
225
226 /*
227  * Interpret `xlat' as an array of flags
228  * print the entries whose bits are on in `flags'
229  * return # of flags printed.
230  */
231 void
232 addflags(const struct xlat *xlat, int flags)
233 {
234         for (; xlat->str; xlat++) {
235                 if (xlat->val && (flags & xlat->val) == xlat->val) {
236                         tprintf("|%s", xlat->str);
237                         flags &= ~xlat->val;
238                 }
239         }
240         if (flags) {
241                 tprintf("|%#x", flags);
242         }
243 }
244
245 /*
246  * Interpret `xlat' as an array of flags.
247  * Print to static string the entries whose bits are on in `flags'
248  * Return static string.
249  */
250 const char *
251 sprintflags(const char *prefix, const struct xlat *xlat, int flags)
252 {
253         static char outstr[1024];
254         char *outptr;
255         int found = 0;
256
257         outptr = stpcpy(outstr, prefix);
258
259         for (; xlat->str; xlat++) {
260                 if ((flags & xlat->val) == xlat->val) {
261                         if (found)
262                                 *outptr++ = '|';
263                         outptr = stpcpy(outptr, xlat->str);
264                         found = 1;
265                         flags &= ~xlat->val;
266                         if (!flags)
267                                 break;
268                 }
269         }
270         if (flags) {
271                 if (found)
272                         *outptr++ = '|';
273                 outptr += sprintf(outptr, "%#x", flags);
274         }
275
276         return outstr;
277 }
278
279 int
280 printflags(const struct xlat *xlat, int flags, const char *dflt)
281 {
282         int n;
283         const char *sep;
284
285         if (flags == 0 && xlat->val == 0) {
286                 tprints(xlat->str);
287                 return 1;
288         }
289
290         sep = "";
291         for (n = 0; xlat->str; xlat++) {
292                 if (xlat->val && (flags & xlat->val) == xlat->val) {
293                         tprintf("%s%s", sep, xlat->str);
294                         flags &= ~xlat->val;
295                         sep = "|";
296                         n++;
297                 }
298         }
299
300         if (n) {
301                 if (flags) {
302                         tprintf("%s%#x", sep, flags);
303                         n++;
304                 }
305         } else {
306                 if (flags) {
307                         tprintf("%#x", flags);
308                         if (dflt)
309                                 tprintf(" /* %s */", dflt);
310                 } else {
311                         if (dflt)
312                                 tprints("0");
313                 }
314         }
315
316         return n;
317 }
318
319 void
320 printnum(struct tcb *tcp, long addr, const char *fmt)
321 {
322         long num;
323
324         if (!addr) {
325                 tprints("NULL");
326                 return;
327         }
328         if (umove(tcp, addr, &num) < 0) {
329                 tprintf("%#lx", addr);
330                 return;
331         }
332         tprints("[");
333         tprintf(fmt, num);
334         tprints("]");
335 }
336
337 void
338 printnum_int(struct tcb *tcp, long addr, const char *fmt)
339 {
340         int num;
341
342         if (!addr) {
343                 tprints("NULL");
344                 return;
345         }
346         if (umove(tcp, addr, &num) < 0) {
347                 tprintf("%#lx", addr);
348                 return;
349         }
350         tprints("[");
351         tprintf(fmt, num);
352         tprints("]");
353 }
354
355 void
356 printfd(struct tcb *tcp, int fd)
357 {
358         const char *p;
359
360         if (show_fd_path && (p = getfdpath(tcp, fd)))
361                 tprintf("%d<%s>", fd, p);
362         else
363                 tprintf("%d", fd);
364 }
365
366 void
367 printuid(const char *text, unsigned long uid)
368 {
369         tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
370 }
371
372 /*
373  * Quote string `instr' of length `size'
374  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
375  * If `len' < 0, treat `instr' as a NUL-terminated string
376  * and quote at most (`size' - 1) bytes.
377  *
378  * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
379  * Note that if len >= 0, always returns 1.
380  */
381 static int
382 string_quote(const char *instr, char *outstr, int len, int size)
383 {
384         const unsigned char *ustr = (const unsigned char *) instr;
385         char *s = outstr;
386         int usehex, c, i, eol;
387
388         eol = 0x100; /* this can never match a char */
389         if (len < 0) {
390                 size--;
391                 eol = '\0';
392         }
393
394         usehex = 0;
395         if (xflag > 1)
396                 usehex = 1;
397         else if (xflag) {
398                 /* Check for presence of symbol which require
399                    to hex-quote the whole string. */
400                 for (i = 0; i < size; ++i) {
401                         c = ustr[i];
402                         /* Check for NUL-terminated string. */
403                         if (c == eol)
404                                 break;
405                         if (!isprint(c) && !isspace(c)) {
406                                 usehex = 1;
407                                 break;
408                         }
409                 }
410         }
411
412         *s++ = '\"';
413
414         if (usehex) {
415                 /* Hex-quote the whole string. */
416                 for (i = 0; i < size; ++i) {
417                         c = ustr[i];
418                         /* Check for NUL-terminated string. */
419                         if (c == eol)
420                                 goto asciz_ended;
421                         *s++ = '\\';
422                         *s++ = 'x';
423                         *s++ = "0123456789abcdef"[c >> 4];
424                         *s++ = "0123456789abcdef"[c & 0xf];
425                 }
426         } else {
427                 for (i = 0; i < size; ++i) {
428                         c = ustr[i];
429                         /* Check for NUL-terminated string. */
430                         if (c == eol)
431                                 goto asciz_ended;
432                         switch (c) {
433                                 case '\"': case '\\':
434                                         *s++ = '\\';
435                                         *s++ = c;
436                                         break;
437                                 case '\f':
438                                         *s++ = '\\';
439                                         *s++ = 'f';
440                                         break;
441                                 case '\n':
442                                         *s++ = '\\';
443                                         *s++ = 'n';
444                                         break;
445                                 case '\r':
446                                         *s++ = '\\';
447                                         *s++ = 'r';
448                                         break;
449                                 case '\t':
450                                         *s++ = '\\';
451                                         *s++ = 't';
452                                         break;
453                                 case '\v':
454                                         *s++ = '\\';
455                                         *s++ = 'v';
456                                         break;
457                                 default:
458                                         if (isprint(c))
459                                                 *s++ = c;
460                                         else {
461                                                 /* Print \octal */
462                                                 *s++ = '\\';
463                                                 if (i + 1 < size
464                                                     && ustr[i + 1] >= '0'
465                                                     && ustr[i + 1] <= '9'
466                                                 ) {
467                                                         /* Print \ooo */
468                                                         *s++ = '0' + (c >> 6);
469                                                         *s++ = '0' + ((c >> 3) & 0x7);
470                                                 } else {
471                                                         /* Print \[[o]o]o */
472                                                         if ((c >> 3) != 0) {
473                                                                 if ((c >> 6) != 0)
474                                                                         *s++ = '0' + (c >> 6);
475                                                                 *s++ = '0' + ((c >> 3) & 0x7);
476                                                         }
477                                                 }
478                                                 *s++ = '0' + (c & 0x7);
479                                         }
480                                         break;
481                         }
482                 }
483         }
484
485         *s++ = '\"';
486         *s = '\0';
487
488         /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
489         if (len < 0 && ustr[i] == '\0') {
490                 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
491                  * but next char is NUL.
492                  */
493                 return 0;
494         }
495
496         return 1;
497
498  asciz_ended:
499         *s++ = '\"';
500         *s = '\0';
501         /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
502         return 0;
503 }
504
505 /*
506  * Print path string specified by address `addr' and length `n'.
507  * If path length exceeds `n', append `...' to the output.
508  */
509 void
510 printpathn(struct tcb *tcp, long addr, int n)
511 {
512         char path[MAXPATHLEN + 1];
513         int nul_seen;
514
515         if (!addr) {
516                 tprints("NULL");
517                 return;
518         }
519
520         /* Cap path length to the path buffer size */
521         if (n > sizeof path - 1)
522                 n = sizeof path - 1;
523
524         /* Fetch one byte more to find out whether path length > n. */
525         nul_seen = umovestr(tcp, addr, n + 1, path);
526         if (nul_seen < 0)
527                 tprintf("%#lx", addr);
528         else {
529                 char *outstr;
530
531                 path[n] = '\0';
532                 n++;
533                 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
534                 string_quote(path, outstr, -1, n);
535                 tprints(outstr);
536                 if (!nul_seen)
537                         tprints("...");
538         }
539 }
540
541 void
542 printpath(struct tcb *tcp, long addr)
543 {
544         /* Size must correspond to char path[] size in printpathn */
545         printpathn(tcp, addr, MAXPATHLEN);
546 }
547
548 /*
549  * Print string specified by address `addr' and length `len'.
550  * If `len' < 0, treat the string as a NUL-terminated string.
551  * If string length exceeds `max_strlen', append `...' to the output.
552  */
553 void
554 printstr(struct tcb *tcp, long addr, int len)
555 {
556         static char *str = NULL;
557         static char *outstr;
558         int size;
559         int ellipsis;
560
561         if (!addr) {
562                 tprints("NULL");
563                 return;
564         }
565         /* Allocate static buffers if they are not allocated yet. */
566         if (!str) {
567                 str = malloc(max_strlen + 1);
568                 if (!str)
569                         die_out_of_memory();
570                 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
571                 if (!outstr)
572                         die_out_of_memory();
573         }
574
575         if (len < 0) {
576                 /*
577                  * Treat as a NUL-terminated string: fetch one byte more
578                  * because string_quote() quotes one byte less.
579                  */
580                 size = max_strlen + 1;
581                 if (umovestr(tcp, addr, size, str) < 0) {
582                         tprintf("%#lx", addr);
583                         return;
584                 }
585         }
586         else {
587                 size = MIN(len, max_strlen);
588                 if (umoven(tcp, addr, size, str) < 0) {
589                         tprintf("%#lx", addr);
590                         return;
591                 }
592         }
593
594         /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
595          * or we were requested to print more than -s NUM chars)...
596          */
597         ellipsis = (string_quote(str, outstr, len, size) &&
598                         (len < 0 || len > max_strlen));
599
600         tprints(outstr);
601         if (ellipsis)
602                 tprints("...");
603 }
604
605 #if HAVE_SYS_UIO_H
606 void
607 dumpiov(struct tcb *tcp, int len, long addr)
608 {
609 #if SUPPORTED_PERSONALITIES > 1
610         union {
611                 struct { u_int32_t base; u_int32_t len; } *iov32;
612                 struct { u_int64_t base; u_int64_t len; } *iov64;
613         } iovu;
614 #define iov iovu.iov64
615 #define sizeof_iov \
616         (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
617 #define iov_iov_base(i) \
618         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
619 #define iov_iov_len(i) \
620         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
621 #else
622         struct iovec *iov;
623 #define sizeof_iov sizeof(*iov)
624 #define iov_iov_base(i) iov[i].iov_base
625 #define iov_iov_len(i) iov[i].iov_len
626 #endif
627         int i;
628         unsigned size;
629
630         size = sizeof_iov * len;
631         /* Assuming no sane program has millions of iovs */
632         if ((unsigned)len > 1024*1024 /* insane or negative size? */
633             || (iov = malloc(size)) == NULL) {
634                 fprintf(stderr, "Out of memory\n");
635                 return;
636         }
637         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
638                 for (i = 0; i < len; i++) {
639                         /* include the buffer number to make it easy to
640                          * match up the trace with the source */
641                         tprintf(" * %lu bytes in buffer %d\n",
642                                 (unsigned long)iov_iov_len(i), i);
643                         dumpstr(tcp, (long) iov_iov_base(i),
644                                 iov_iov_len(i));
645                 }
646         }
647         free(iov);
648 #undef sizeof_iov
649 #undef iov_iov_base
650 #undef iov_iov_len
651 #undef iov
652 }
653 #endif
654
655 void
656 dumpstr(struct tcb *tcp, long addr, int len)
657 {
658         static int strsize = -1;
659         static unsigned char *str;
660         char *s;
661         int i, j;
662
663         if (strsize < len) {
664                 free(str);
665                 str = malloc(len);
666                 if (!str) {
667                         strsize = -1;
668                         fprintf(stderr, "Out of memory\n");
669                         return;
670                 }
671                 strsize = len;
672         }
673
674         if (umoven(tcp, addr, len, (char *) str) < 0)
675                 return;
676
677         for (i = 0; i < len; i += 16) {
678                 char outstr[80];
679
680                 s = outstr;
681                 sprintf(s, " | %05x ", i);
682                 s += 9;
683                 for (j = 0; j < 16; j++) {
684                         if (j == 8)
685                                 *s++ = ' ';
686                         if (i + j < len) {
687                                 sprintf(s, " %02x", str[i + j]);
688                                 s += 3;
689                         }
690                         else {
691                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
692                         }
693                 }
694                 *s++ = ' '; *s++ = ' ';
695                 for (j = 0; j < 16; j++) {
696                         if (j == 8)
697                                 *s++ = ' ';
698                         if (i + j < len) {
699                                 if (isprint(str[i + j]))
700                                         *s++ = str[i + j];
701                                 else
702                                         *s++ = '.';
703                         }
704                         else
705                                 *s++ = ' ';
706                 }
707                 tprintf("%s |\n", outstr);
708         }
709 }
710
711 #ifdef HAVE_PROCESS_VM_READV
712 /* C library supports this, but the kernel might not. */
713 static bool process_vm_readv_not_supported = 0;
714 #else
715
716 /* Need to do this since process_vm_readv() is not yet available in libc.
717  * When libc is be updated, only "static bool process_vm_readv_not_supported"
718  * line should remain.
719  */
720 #if !defined(__NR_process_vm_readv)
721 # if defined(I386)
722 #  define __NR_process_vm_readv  347
723 # elif defined(X86_64)
724 #  define __NR_process_vm_readv  310
725 # elif defined(POWERPC)
726 #  define __NR_process_vm_readv  351
727 # endif
728 #endif
729
730 #if defined(__NR_process_vm_readv)
731 static bool process_vm_readv_not_supported = 0;
732 static ssize_t process_vm_readv(pid_t pid,
733                  const struct iovec *lvec,
734                  unsigned long liovcnt,
735                  const struct iovec *rvec,
736                  unsigned long riovcnt,
737                  unsigned long flags)
738 {
739         return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
740 }
741 #else
742 static bool process_vm_readv_not_supported = 1;
743 # define process_vm_readv(...) (errno = ENOSYS, -1)
744 #endif
745
746 #endif /* end of hack */
747
748 #define PAGMASK (~(PAGSIZ - 1))
749 /*
750  * move `len' bytes of data from process `pid'
751  * at address `addr' to our space at `laddr'
752  */
753 int
754 umoven(struct tcb *tcp, long addr, int len, char *laddr)
755 {
756         int pid = tcp->pid;
757         int n, m;
758         int started;
759         union {
760                 long val;
761                 char x[sizeof(long)];
762         } u;
763
764 #if SUPPORTED_PERSONALITIES > 1
765         if (current_wordsize < sizeof(addr))
766                 addr &= (1ul << 8 * current_wordsize) - 1;
767 #endif
768
769         if (!process_vm_readv_not_supported) {
770                 struct iovec local[1], remote[1];
771                 int r;
772
773                 local[0].iov_base = laddr;
774                 remote[0].iov_base = (void*)addr;
775                 local[0].iov_len = remote[0].iov_len = len;
776                 r = process_vm_readv(pid,
777                                 local, 1,
778                                 remote, 1,
779                                 /*flags:*/ 0
780                 );
781                 if (r < 0) {
782                         if (errno == ENOSYS)
783                                 process_vm_readv_not_supported = 1;
784                         else if (errno != EINVAL) /* EINVAL is seen if process is gone */
785                                 /* strange... */
786                                 perror("process_vm_readv");
787                         goto vm_readv_didnt_work;
788                 }
789                 return r;
790         }
791  vm_readv_didnt_work:
792
793         started = 0;
794         if (addr & (sizeof(long) - 1)) {
795                 /* addr not a multiple of sizeof(long) */
796                 n = addr - (addr & -sizeof(long)); /* residue */
797                 addr &= -sizeof(long); /* residue */
798                 errno = 0;
799                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
800                 if (errno) {
801                         /* But if not started, we had a bogus address. */
802                         if (addr != 0 && errno != EIO && errno != ESRCH)
803                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
804                         return -1;
805                 }
806                 started = 1;
807                 m = MIN(sizeof(long) - n, len);
808                 memcpy(laddr, &u.x[n], m);
809                 addr += sizeof(long), laddr += m, len -= m;
810         }
811         while (len) {
812                 errno = 0;
813                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
814                 if (errno) {
815                         if (started && (errno==EPERM || errno==EIO)) {
816                                 /* Ran into 'end of memory' - stupid "printpath" */
817                                 return 0;
818                         }
819                         if (addr != 0 && errno != EIO && errno != ESRCH)
820                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
821                         return -1;
822                 }
823                 started = 1;
824                 m = MIN(sizeof(long), len);
825                 memcpy(laddr, u.x, m);
826                 addr += sizeof(long), laddr += m, len -= m;
827         }
828
829         return 0;
830 }
831
832 /*
833  * Like `umove' but make the additional effort of looking
834  * for a terminating zero byte.
835  *
836  * Returns < 0 on error, > 0 if NUL was seen,
837  * (TODO if useful: return count of bytes including NUL),
838  * else 0 if len bytes were read but no NUL byte seen.
839  *
840  * Note: there is no guarantee we won't overwrite some bytes
841  * in laddr[] _after_ terminating NUL (but, of course,
842  * we never write past laddr[len-1]).
843  */
844 int
845 umovestr(struct tcb *tcp, long addr, int len, char *laddr)
846 {
847         int started;
848         int pid = tcp->pid;
849         int i, n, m;
850         union {
851                 long val;
852                 char x[sizeof(long)];
853         } u;
854
855 #if SUPPORTED_PERSONALITIES > 1
856         if (current_wordsize < sizeof(addr))
857                 addr &= (1ul << 8 * current_wordsize) - 1;
858 #endif
859
860         if (!process_vm_readv_not_supported) {
861                 struct iovec local[1], remote[1];
862
863                 local[0].iov_base = laddr;
864                 remote[0].iov_base = (void*)addr;
865
866                 while (len > 0) {
867                         int end_in_page;
868                         int r;
869                         int chunk_len;
870
871                         /* Don't read kilobytes: most strings are short */
872                         chunk_len = len;
873                         if (chunk_len > 256)
874                                 chunk_len = 256;
875                         /* Don't cross pages. I guess otherwise we can get EFAULT
876                          * and fail to notice that terminating NUL lies
877                          * in the existing (first) page.
878                          * (I hope there aren't arches with pages < 4K)
879                          */
880                         end_in_page = ((addr + chunk_len) & 4095);
881                         r = chunk_len - end_in_page;
882                         if (r > 0) /* if chunk_len > end_in_page */
883                                 chunk_len = r; /* chunk_len -= end_in_page */
884
885                         local[0].iov_len = remote[0].iov_len = chunk_len;
886                         r = process_vm_readv(pid,
887                                         local, 1,
888                                         remote, 1,
889                                         /*flags:*/ 0
890                         );
891                         if (r < 0) {
892                                 if (errno == ENOSYS)
893                                         process_vm_readv_not_supported = 1;
894                                 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
895                                         /* strange... */
896                                         perror("process_vm_readv");
897                                 goto vm_readv_didnt_work;
898                         }
899                         if (memchr(local[0].iov_base, '\0', r))
900                                 return 1;
901                         local[0].iov_base += r;
902                         remote[0].iov_base += r;
903                         len -= r;
904                 }
905                 return 0;
906         }
907  vm_readv_didnt_work:
908
909         started = 0;
910         if (addr & (sizeof(long) - 1)) {
911                 /* addr not a multiple of sizeof(long) */
912                 n = addr - (addr & -sizeof(long)); /* residue */
913                 addr &= -sizeof(long); /* residue */
914                 errno = 0;
915                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
916                 if (errno) {
917                         if (addr != 0 && errno != EIO && errno != ESRCH)
918                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
919                         return -1;
920                 }
921                 started = 1;
922                 m = MIN(sizeof(long) - n, len);
923                 memcpy(laddr, &u.x[n], m);
924                 while (n & (sizeof(long) - 1))
925                         if (u.x[n++] == '\0')
926                                 return 1;
927                 addr += sizeof(long), laddr += m, len -= m;
928         }
929         while (len) {
930                 errno = 0;
931                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
932                 if (errno) {
933                         if (started && (errno==EPERM || errno==EIO)) {
934                                 /* Ran into 'end of memory' - stupid "printpath" */
935                                 return 0;
936                         }
937                         if (addr != 0 && errno != EIO && errno != ESRCH)
938                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
939                         return -1;
940                 }
941                 started = 1;
942                 m = MIN(sizeof(long), len);
943                 memcpy(laddr, u.x, m);
944                 for (i = 0; i < sizeof(long); i++)
945                         if (u.x[i] == '\0')
946                                 return 1;
947                 addr += sizeof(long), laddr += m, len -= m;
948         }
949         return 0;
950 }
951
952 int
953 upeek(struct tcb *tcp, long off, long *res)
954 {
955         long val;
956
957         errno = 0;
958         val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
959         if (val == -1 && errno) {
960                 if (errno != ESRCH) {
961                         perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
962                 }
963                 return -1;
964         }
965         *res = val;
966         return 0;
967 }
968
969 void
970 printcall(struct tcb *tcp)
971 {
972 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
973                            sizeof(long) == 8 ? "[????????????????] " : \
974                            NULL /* crash */)
975
976 #if defined(I386)
977         long eip;
978
979         if (upeek(tcp, 4*EIP, &eip) < 0) {
980                 PRINTBADPC;
981                 return;
982         }
983         tprintf("[%08lx] ", eip);
984 #elif defined(S390) || defined(S390X)
985         long psw;
986         if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
987                 PRINTBADPC;
988                 return;
989         }
990 # ifdef S390
991         tprintf("[%08lx] ", psw);
992 # elif S390X
993         tprintf("[%16lx] ", psw);
994 # endif
995
996 #elif defined(X86_64)
997         long rip;
998
999         if (upeek(tcp, 8*RIP, &rip) < 0) {
1000                 PRINTBADPC;
1001                 return;
1002         }
1003         tprintf("[%16lx] ", rip);
1004 #elif defined(IA64)
1005         long ip;
1006
1007         if (upeek(tcp, PT_B0, &ip) < 0) {
1008                 PRINTBADPC;
1009                 return;
1010         }
1011         tprintf("[%08lx] ", ip);
1012 #elif defined(POWERPC)
1013         long pc;
1014
1015         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1016                 PRINTBADPC;
1017                 return;
1018         }
1019 # ifdef POWERPC64
1020         tprintf("[%016lx] ", pc);
1021 # else
1022         tprintf("[%08lx] ", pc);
1023 # endif
1024 #elif defined(M68K)
1025         long pc;
1026
1027         if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1028                 tprints("[????????] ");
1029                 return;
1030         }
1031         tprintf("[%08lx] ", pc);
1032 #elif defined(ALPHA)
1033         long pc;
1034
1035         if (upeek(tcp, REG_PC, &pc) < 0) {
1036                 tprints("[????????????????] ");
1037                 return;
1038         }
1039         tprintf("[%08lx] ", pc);
1040 #elif defined(SPARC) || defined(SPARC64)
1041         struct pt_regs regs;
1042         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1043                 PRINTBADPC;
1044                 return;
1045         }
1046 # if defined(SPARC64)
1047         tprintf("[%08lx] ", regs.tpc);
1048 # else
1049         tprintf("[%08lx] ", regs.pc);
1050 # endif
1051 #elif defined(HPPA)
1052         long pc;
1053
1054         if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1055                 tprints("[????????] ");
1056                 return;
1057         }
1058         tprintf("[%08lx] ", pc);
1059 #elif defined(MIPS)
1060         long pc;
1061
1062         if (upeek(tcp, REG_EPC, &pc) < 0) {
1063                 tprints("[????????] ");
1064                 return;
1065         }
1066         tprintf("[%08lx] ", pc);
1067 #elif defined(SH)
1068         long pc;
1069
1070         if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1071                 tprints("[????????] ");
1072                 return;
1073         }
1074         tprintf("[%08lx] ", pc);
1075 #elif defined(SH64)
1076         long pc;
1077
1078         if (upeek(tcp, REG_PC, &pc) < 0) {
1079                 tprints("[????????????????] ");
1080                 return;
1081         }
1082         tprintf("[%08lx] ", pc);
1083 #elif defined(ARM)
1084         long pc;
1085
1086         if (upeek(tcp, 4*15, &pc) < 0) {
1087                 PRINTBADPC;
1088                 return;
1089         }
1090         tprintf("[%08lx] ", pc);
1091 #elif defined(AVR32)
1092         long pc;
1093
1094         if (upeek(tcp, REG_PC, &pc) < 0) {
1095                 tprints("[????????] ");
1096                 return;
1097         }
1098         tprintf("[%08lx] ", pc);
1099 #elif defined(BFIN)
1100         long pc;
1101
1102         if (upeek(tcp, PT_PC, &pc) < 0) {
1103                 PRINTBADPC;
1104                 return;
1105         }
1106         tprintf("[%08lx] ", pc);
1107 #elif defined(CRISV10)
1108         long pc;
1109
1110         if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1111                 PRINTBADPC;
1112                 return;
1113         }
1114         tprintf("[%08lx] ", pc);
1115 #elif defined(CRISV32)
1116         long pc;
1117
1118         if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1119                 PRINTBADPC;
1120                 return;
1121         }
1122         tprintf("[%08lx] ", pc);
1123 #endif /* architecture */
1124 }
1125
1126 /*
1127  * These #if's are huge, please indent them correctly.
1128  * It's easy to get confused otherwise.
1129  */
1130
1131 #include "syscall.h"
1132
1133 #ifndef CLONE_PTRACE
1134 # define CLONE_PTRACE    0x00002000
1135 #endif
1136 #ifndef CLONE_VFORK
1137 # define CLONE_VFORK     0x00004000
1138 #endif
1139 #ifndef CLONE_VM
1140 # define CLONE_VM        0x00000100
1141 #endif
1142
1143 static int
1144 change_syscall(struct tcb *tcp, int new)
1145 {
1146 #if defined(I386)
1147         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1148                 return -1;
1149         return 0;
1150 #elif defined(X86_64)
1151         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1152                 return -1;
1153         return 0;
1154 #elif defined(POWERPC)
1155         if (ptrace(PTRACE_POKEUSER, tcp->pid,
1156                    (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1157                 return -1;
1158         return 0;
1159 #elif defined(S390) || defined(S390X)
1160         /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1161         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1162                 return -1;
1163         return 0;
1164 #elif defined(M68K)
1165         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1166                 return -1;
1167         return 0;
1168 #elif defined(SPARC) || defined(SPARC64)
1169         struct pt_regs regs;
1170         if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1171                 return -1;
1172         regs.u_regs[U_REG_G1] = new;
1173         if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1174                 return -1;
1175         return 0;
1176 #elif defined(MIPS)
1177         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1178                 return -1;
1179         return 0;
1180 #elif defined(ALPHA)
1181         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1182                 return -1;
1183         return 0;
1184 #elif defined(AVR32)
1185         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1186                 return -1;
1187         return 0;
1188 #elif defined(BFIN)
1189         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1190                 return -1;
1191         return 0;
1192 #elif defined(IA64)
1193         if (ia32) {
1194                 switch (new) {
1195                 case 2:
1196                         break;  /* x86 SYS_fork */
1197                 case SYS_clone:
1198                         new = 120;
1199                         break;
1200                 default:
1201                         fprintf(stderr, "%s: unexpected syscall %d\n",
1202                                 __FUNCTION__, new);
1203                         return -1;
1204                 }
1205                 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1206                         return -1;
1207         } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1208                 return -1;
1209         return 0;
1210 #elif defined(HPPA)
1211         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1212                 return -1;
1213         return 0;
1214 #elif defined(SH)
1215         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1216                 return -1;
1217         return 0;
1218 #elif defined(SH64)
1219         /* Top half of reg encodes the no. of args n as 0x1n.
1220            Assume 0 args as kernel never actually checks... */
1221         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1222                                 0x100000 | new) < 0)
1223                 return -1;
1224         return 0;
1225 #elif defined(CRISV10) || defined(CRISV32)
1226         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1227                 return -1;
1228         return 0;
1229 #elif defined(ARM)
1230         /* Some kernels support this, some (pre-2.6.16 or so) don't.  */
1231 # ifndef PTRACE_SET_SYSCALL
1232 #  define PTRACE_SET_SYSCALL 23
1233 # endif
1234         if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1235                 return -1;
1236         return 0;
1237 #elif defined(TILE)
1238         if (ptrace(PTRACE_POKEUSER, tcp->pid,
1239                    (char*)PTREGS_OFFSET_REG(0),
1240                    new) != 0)
1241                 return -1;
1242         return 0;
1243 #elif defined(MICROBLAZE)
1244         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1245                 return -1;
1246         return 0;
1247 #else
1248 #warning Do not know how to handle change_syscall for this architecture
1249 #endif /* architecture */
1250         return -1;
1251 }
1252
1253 #ifdef IA64
1254
1255 typedef unsigned long *arg_setup_state;
1256
1257 static int
1258 arg_setup(struct tcb *tcp, arg_setup_state *state)
1259 {
1260         unsigned long cfm, sof, sol;
1261         long bsp;
1262
1263         if (ia32) {
1264                 /* Satisfy a false GCC warning.  */
1265                 *state = NULL;
1266                 return 0;
1267         }
1268
1269         if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1270                 return -1;
1271         if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1272                 return -1;
1273
1274         sof = (cfm >> 0) & 0x7f;
1275         sol = (cfm >> 7) & 0x7f;
1276         bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1277
1278         *state = (unsigned long *) bsp;
1279         return 0;
1280 }
1281
1282 # define arg_finish_change(tcp, state)  0
1283
1284 static int
1285 get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1286 {
1287         int ret;
1288
1289         if (ia32)
1290                 ret = upeek(tcp, PT_R11, valp);
1291         else
1292                 ret = umoven(tcp,
1293                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1294                               sizeof(long), (void *) valp);
1295         return ret;
1296 }
1297
1298 static int
1299 get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1300 {
1301         int ret;
1302
1303         if (ia32)
1304                 ret = upeek(tcp, PT_R9, valp);
1305         else
1306                 ret = umoven(tcp,
1307                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1308                               sizeof(long), (void *) valp);
1309         return ret;
1310 }
1311
1312 static int
1313 set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1314 {
1315         int req = PTRACE_POKEDATA;
1316         void *ap;
1317
1318         if (ia32) {
1319                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1320                 req = PTRACE_POKEUSER;
1321         } else
1322                 ap = ia64_rse_skip_regs(*state, 0);
1323         errno = 0;
1324         ptrace(req, tcp->pid, ap, val);
1325         return errno ? -1 : 0;
1326 }
1327
1328 static int
1329 set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1330 {
1331         int req = PTRACE_POKEDATA;
1332         void *ap;
1333
1334         if (ia32) {
1335                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1336                 req = PTRACE_POKEUSER;
1337         } else
1338                 ap = ia64_rse_skip_regs(*state, 1);
1339         errno = 0;
1340         ptrace(req, tcp->pid, ap, val);
1341         return errno ? -1 : 0;
1342 }
1343
1344 /* ia64 does not return the input arguments from functions (and syscalls)
1345    according to ia64 RSE (Register Stack Engine) behavior.  */
1346
1347 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1348 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1349
1350 #elif defined(SPARC) || defined(SPARC64)
1351
1352 typedef struct pt_regs arg_setup_state;
1353
1354 # define arg_setup(tcp, state) \
1355     (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1356 # define arg_finish_change(tcp, state) \
1357     (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
1358
1359 # define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1360 # define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1361 # define set_arg0(tcp, state, val)  ((state)->u_regs[U_REG_O0] = (val), 0)
1362 # define set_arg1(tcp, state, val)  ((state)->u_regs[U_REG_O1] = (val), 0)
1363 # define restore_arg0(tcp, state, val) 0
1364
1365 #else /* other architectures */
1366
1367 # if defined S390 || defined S390X
1368 /* Note: this is only true for the `clone' system call, which handles
1369    arguments specially.  We could as well say that its first two arguments
1370    are swapped relative to other architectures, but that would just be
1371    another #ifdef in the calls.  */
1372 #  define arg0_offset   PT_GPR3
1373 #  define arg1_offset   PT_ORIGGPR2
1374 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1375 #  define restore_arg1(tcp, state, val) ((void) (state), 0)
1376 #  define arg0_index    1
1377 #  define arg1_index    0
1378 # elif defined(ALPHA) || defined(MIPS)
1379 #  define arg0_offset   REG_A0
1380 #  define arg1_offset   (REG_A0+1)
1381 # elif defined(AVR32)
1382 #  define arg0_offset   (REG_R12)
1383 #  define arg1_offset   (REG_R11)
1384 # elif defined(POWERPC)
1385 #  define arg0_offset   (sizeof(unsigned long)*PT_R3)
1386 #  define arg1_offset   (sizeof(unsigned long)*PT_R4)
1387 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1388 # elif defined(HPPA)
1389 #  define arg0_offset   PT_GR26
1390 #  define arg1_offset   (PT_GR26-4)
1391 # elif defined(X86_64)
1392 #  define arg0_offset   ((long)(8*(current_personality ? RBX : RDI)))
1393 #  define arg1_offset   ((long)(8*(current_personality ? RCX : RSI)))
1394 # elif defined(SH)
1395 #  define arg0_offset   (4*(REG_REG0+4))
1396 #  define arg1_offset   (4*(REG_REG0+5))
1397 # elif defined(SH64)
1398    /* ABI defines arg0 & 1 in r2 & r3 */
1399 #  define arg0_offset   (REG_OFFSET+16)
1400 #  define arg1_offset   (REG_OFFSET+24)
1401 #  define restore_arg0(tcp, state, val) 0
1402 # elif defined CRISV10 || defined CRISV32
1403 #  define arg0_offset   (4*PT_R11)
1404 #  define arg1_offset   (4*PT_ORIG_R10)
1405 #  define restore_arg0(tcp, state, val) 0
1406 #  define restore_arg1(tcp, state, val) 0
1407 #  define arg0_index    1
1408 #  define arg1_index    0
1409 # else
1410 #  define arg0_offset   0
1411 #  define arg1_offset   4
1412 #  if defined ARM
1413 #   define restore_arg0(tcp, state, val) 0
1414 #  endif
1415 # endif
1416
1417 typedef int arg_setup_state;
1418
1419 # define arg_setup(tcp, state)         (0)
1420 # define arg_finish_change(tcp, state) 0
1421 # define get_arg0(tcp, cookie, valp)   (upeek((tcp), arg0_offset, (valp)))
1422 # define get_arg1(tcp, cookie, valp)   (upeek((tcp), arg1_offset, (valp)))
1423
1424 static int
1425 set_arg0(struct tcb *tcp, void *cookie, long val)
1426 {
1427         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1428 }
1429
1430 static int
1431 set_arg1(struct tcb *tcp, void *cookie, long val)
1432 {
1433         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1434 }
1435
1436 #endif /* architectures */
1437
1438 #ifndef restore_arg0
1439 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1440 #endif
1441 #ifndef restore_arg1
1442 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1443 #endif
1444
1445 #ifndef arg0_index
1446 # define arg0_index 0
1447 # define arg1_index 1
1448 #endif
1449
1450 int
1451 setbpt(struct tcb *tcp)
1452 {
1453         static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1454         arg_setup_state state;
1455
1456         if (tcp->flags & TCB_BPTSET) {
1457                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1458                 return -1;
1459         }
1460
1461         /*
1462          * It's a silly kludge to initialize this with a search at runtime.
1463          * But it's better than maintaining another magic thing in the
1464          * godforsaken tables.
1465          */
1466         if (clone_scno[current_personality] == 0) {
1467                 int i;
1468                 for (i = 0; i < nsyscalls; ++i)
1469                         if (sysent[i].sys_func == sys_clone) {
1470                                 clone_scno[current_personality] = i;
1471                                 break;
1472                         }
1473         }
1474
1475         if (sysent[tcp->scno].sys_func == sys_fork ||
1476             sysent[tcp->scno].sys_func == sys_vfork) {
1477                 if (arg_setup(tcp, &state) < 0
1478                     || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1479                     || get_arg1(tcp, &state, &tcp->inst[1]) < 0
1480                     || change_syscall(tcp, clone_scno[current_personality]) < 0
1481                     || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1482                     || set_arg1(tcp, &state, 0) < 0
1483                     || arg_finish_change(tcp, &state) < 0)
1484                         return -1;
1485                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1486                 tcp->u_arg[arg1_index] = 0;
1487                 tcp->flags |= TCB_BPTSET;
1488                 return 0;
1489         }
1490
1491         if (sysent[tcp->scno].sys_func == sys_clone) {
1492                 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1493                    contrary to x86 vfork above.  Even on x86 we turn the
1494                    vfork semantics into plain fork - each application must not
1495                    depend on the vfork specifics according to POSIX.  We would
1496                    hang waiting for the parent resume otherwise.  We need to
1497                    clear also CLONE_VM but only in the CLONE_VFORK case as
1498                    otherwise we would break pthread_create.  */
1499
1500                 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1501                 if (new_arg0 & CLONE_VFORK)
1502                         new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1503                 if (arg_setup(tcp, &state) < 0
1504                  || set_arg0(tcp, &state, new_arg0) < 0
1505                  || arg_finish_change(tcp, &state) < 0)
1506                         return -1;
1507                 tcp->flags |= TCB_BPTSET;
1508                 tcp->inst[0] = tcp->u_arg[arg0_index];
1509                 tcp->inst[1] = tcp->u_arg[arg1_index];
1510                 return 0;
1511         }
1512
1513         fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1514                 tcp->scno, tcp->pid);
1515         return -1;
1516 }
1517
1518 int
1519 clearbpt(struct tcb *tcp)
1520 {
1521         arg_setup_state state;
1522         if (arg_setup(tcp, &state) < 0
1523             || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1524             || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1525             || arg_finish_change(tcp, &state))
1526                 if (errno != ESRCH)
1527                         return -1;
1528         tcp->flags &= ~TCB_BPTSET;
1529         return 0;
1530 }