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