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