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