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