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