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