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