]> granicus.if.org Git - strace/blob - util.c
Optimize get_scno function
[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  *      $Id$
34  */
35
36 #include "defs.h"
37
38 #include <signal.h>
39 #include <sys/syscall.h>
40 #include <sys/user.h>
41 #include <sys/param.h>
42 #include <fcntl.h>
43 #if HAVE_SYS_UIO_H
44 #include <sys/uio.h>
45 #endif
46 #ifdef SUNOS4
47 #include <machine/reg.h>
48 #include <a.out.h>
49 #include <link.h>
50 #endif /* SUNOS4 */
51
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
54 #endif
55
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
58 # include <asm/rse.h>
59 #endif
60
61 #ifdef HAVE_SYS_REG_H
62 #include <sys/reg.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
65 #undef PTRACE_SYSCALL
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 #  define ia64_fpreg XXX_ia64_fpreg
68 # endif
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 #  define pt_all_user_regs XXX_pt_all_user_regs
71 # endif
72 #include <linux/ptrace.h>
73 # undef ia64_fpreg
74 # undef pt_all_user_regs
75 #endif
76
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
81 #if defined(LINUXSPARC) && defined (SPARC64)
82 # undef PTRACE_GETREGS
83 # define PTRACE_GETREGS PTRACE_GETREGS64
84 # undef PTRACE_SETREGS
85 # define PTRACE_SETREGS PTRACE_SETREGS64
86 #endif
87
88 /* macros */
89 #ifndef MAX
90 #define MAX(a,b)                (((a) > (b)) ? (a) : (b))
91 #endif
92 #ifndef MIN
93 #define MIN(a,b)                (((a) < (b)) ? (a) : (b))
94 #endif
95
96 int
97 tv_nz(struct timeval *a)
98 {
99         return a->tv_sec || a->tv_usec;
100 }
101
102 int
103 tv_cmp(struct timeval *a, struct timeval *b)
104 {
105         if (a->tv_sec < b->tv_sec
106             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
107                 return -1;
108         if (a->tv_sec > b->tv_sec
109             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
110                 return 1;
111         return 0;
112 }
113
114 double
115 tv_float(struct timeval *tv)
116 {
117         return tv->tv_sec + tv->tv_usec/1000000.0;
118 }
119
120 void
121 tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
122 {
123         tv->tv_sec = a->tv_sec + b->tv_sec;
124         tv->tv_usec = a->tv_usec + b->tv_usec;
125         if (tv->tv_usec >= 1000000) {
126                 tv->tv_sec++;
127                 tv->tv_usec -= 1000000;
128         }
129 }
130
131 void
132 tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
133 {
134         tv->tv_sec = a->tv_sec - b->tv_sec;
135         tv->tv_usec = a->tv_usec - b->tv_usec;
136         if (((long) tv->tv_usec) < 0) {
137                 tv->tv_sec--;
138                 tv->tv_usec += 1000000;
139         }
140 }
141
142 void
143 tv_div(struct timeval *tv, struct timeval *a, int n)
144 {
145         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
146         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
147         tv->tv_usec %= 1000000;
148 }
149
150 void
151 tv_mul(struct timeval *tv, struct timeval *a, int n)
152 {
153         tv->tv_usec = a->tv_usec * n;
154         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
155         tv->tv_usec %= 1000000;
156 }
157
158 const char *
159 xlookup(const struct xlat *xlat, int val)
160 {
161         for (; xlat->str != NULL; xlat++)
162                 if (xlat->val == val)
163                         return xlat->str;
164         return NULL;
165 }
166
167 /*
168  * Generic ptrace wrapper which tracks ESRCH errors
169  * by setting tcp->ptrace_errno to ESRCH.
170  *
171  * We assume that ESRCH indicates likely process death (SIGKILL?),
172  * modulo bugs where process somehow ended up not stopped.
173  * Unfortunately kernel uses ESRCH for that case too. Oh well.
174  *
175  * Currently used by upeek() only.
176  * TODO: use this in all other ptrace() calls while decoding.
177  */
178 long
179 do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
180 {
181         long l;
182
183         errno = 0;
184         l = ptrace(request, tcp->pid, addr, (long) data);
185         /* Non-ESRCH errors might be our invalid reg/mem accesses,
186          * we do not record them. */
187         if (errno == ESRCH)
188                 tcp->ptrace_errno = ESRCH;
189         return l;
190 }
191
192 /*
193  * Used when we want to unblock stopped traced process.
194  * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
195  * Returns 0 on success or if error was ESRCH
196  * (presumably process was killed while we talk to it).
197  * Otherwise prints error message and returns -1.
198  */
199 int
200 ptrace_restart(int op, struct tcb *tcp, int sig)
201 {
202         int err;
203         const char *msg;
204
205         errno = 0;
206         ptrace(op, tcp->pid, (void *) 1, (long) sig);
207         err = errno;
208         if (!err || err == ESRCH)
209                 return 0;
210
211         tcp->ptrace_errno = err;
212         msg = "SYSCALL";
213         if (op == PTRACE_CONT)
214                 msg = "CONT";
215         if (op == PTRACE_DETACH)
216                 msg = "DETACH";
217         fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
218                         msg, sig, strerror(err));
219         return -1;
220 }
221
222 /*
223  * Print entry in struct xlat table, if there.
224  */
225 void
226 printxval(const struct xlat *xlat, int val, const char *dflt)
227 {
228         const char *str = xlookup(xlat, val);
229
230         if (str)
231                 tprintf("%s", str);
232         else
233                 tprintf("%#x /* %s */", val, dflt);
234 }
235
236 #if HAVE_LONG_LONG
237 /*
238  * Print 64bit argument at position llarg and return the index of the next
239  * argument.
240  */
241 int
242 printllval(struct tcb *tcp, const char *format, int llarg)
243 {
244 # if defined(FREEBSD) \
245      || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
246      || defined(LINUX_MIPSO32) \
247      || defined(__ARM_EABI__)
248         /* Align 64bit argument to 64bit boundary.  */
249         llarg = (llarg + 1) & 0x1e;
250 # endif
251 # if defined LINUX && (defined X86_64 || defined POWERPC64)
252         if (current_personality == 0) {
253                 tprintf(format, tcp->u_arg[llarg]);
254                 llarg++;
255         } else {
256 #  ifdef POWERPC64
257                 /* Align 64bit argument to 64bit boundary.  */
258                 llarg = (llarg + 1) & 0x1e;
259 #  endif
260                 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
261                 llarg += 2;
262         }
263 # elif defined IA64 || defined ALPHA
264         tprintf(format, tcp->u_arg[llarg]);
265         llarg++;
266 # elif defined LINUX_MIPSN32
267         tprintf(format, tcp->ext_arg[llarg]);
268         llarg++;
269 # else
270         tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
271         llarg += 2;
272 # endif
273         return llarg;
274 }
275 #endif
276
277 /*
278  * Interpret `xlat' as an array of flags
279  * print the entries whose bits are on in `flags'
280  * return # of flags printed.
281  */
282 void
283 addflags(const struct xlat *xlat, int flags)
284 {
285         for (; xlat->str; xlat++) {
286                 if (xlat->val && (flags & xlat->val) == xlat->val) {
287                         tprintf("|%s", xlat->str);
288                         flags &= ~xlat->val;
289                 }
290         }
291         if (flags) {
292                 tprintf("|%#x", flags);
293         }
294 }
295
296 /*
297  * Interpret `xlat' as an array of flags.
298  * Print to static string the entries whose bits are on in `flags'
299  * Return static string.
300  */
301 const char *
302 sprintflags(const char *prefix, const struct xlat *xlat, int flags)
303 {
304         static char outstr[1024];
305         int found = 0;
306
307         strcpy(outstr, prefix);
308
309         for (; xlat->str; xlat++) {
310                 if ((flags & xlat->val) == xlat->val) {
311                         if (found)
312                                 strcat(outstr, "|");
313                         strcat(outstr, xlat->str);
314                         flags &= ~xlat->val;
315                         found = 1;
316                 }
317         }
318         if (flags) {
319                 if (found)
320                         strcat(outstr, "|");
321                 sprintf(outstr + strlen(outstr), "%#x", flags);
322         }
323
324         return outstr;
325 }
326
327 int
328 printflags(const struct xlat *xlat, int flags, const char *dflt)
329 {
330         int n;
331         const char *sep;
332
333         if (flags == 0 && xlat->val == 0) {
334                 tprintf("%s", xlat->str);
335                 return 1;
336         }
337
338         sep = "";
339         for (n = 0; xlat->str; xlat++) {
340                 if (xlat->val && (flags & xlat->val) == xlat->val) {
341                         tprintf("%s%s", sep, xlat->str);
342                         flags &= ~xlat->val;
343                         sep = "|";
344                         n++;
345                 }
346         }
347
348         if (n) {
349                 if (flags) {
350                         tprintf("%s%#x", sep, flags);
351                         n++;
352                 }
353         } else {
354                 if (flags) {
355                         tprintf("%#x", flags);
356                         if (dflt)
357                                 tprintf(" /* %s */", dflt);
358                 } else {
359                         if (dflt)
360                                 tprintf("0");
361                 }
362         }
363
364         return n;
365 }
366
367 void
368 printnum(struct tcb *tcp, long addr, const char *fmt)
369 {
370         long num;
371
372         if (!addr) {
373                 tprintf("NULL");
374                 return;
375         }
376         if (umove(tcp, addr, &num) < 0) {
377                 tprintf("%#lx", addr);
378                 return;
379         }
380         tprintf("[");
381         tprintf(fmt, num);
382         tprintf("]");
383 }
384
385 void
386 printnum_int(struct tcb *tcp, long addr, const char *fmt)
387 {
388         int num;
389
390         if (!addr) {
391                 tprintf("NULL");
392                 return;
393         }
394         if (umove(tcp, addr, &num) < 0) {
395                 tprintf("%#lx", addr);
396                 return;
397         }
398         tprintf("[");
399         tprintf(fmt, num);
400         tprintf("]");
401 }
402
403 void
404 printfd(struct tcb *tcp, int fd)
405 {
406         const char *p;
407
408         if (show_fd_path && (p = getfdpath(tcp, fd)))
409                 tprintf("%d<%s>", fd, p);
410         else
411                 tprintf("%d", fd);
412 }
413
414 void
415 printuid(const char *text, unsigned long uid)
416 {
417         tprintf("%s", text);
418         tprintf((uid == -1) ? "%ld" : "%lu", uid);
419 }
420
421 static char path[MAXPATHLEN + 1];
422
423 /*
424  * Quote string `instr' of length `size'
425  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
426  * If `len' < 0, treat `instr' as a NUL-terminated string
427  * and quote at most (`size' - 1) bytes.
428  */
429 static int
430 string_quote(const char *instr, char *outstr, int len, int size)
431 {
432         const unsigned char *ustr = (const unsigned char *) instr;
433         char *s = outstr;
434         int usehex = 0, c, i;
435
436         if (xflag > 1)
437                 usehex = 1;
438         else if (xflag) {
439                 /* Check for presence of symbol which require
440                    to hex-quote the whole string. */
441                 for (i = 0; i < size; ++i) {
442                         c = ustr[i];
443                         /* Check for NUL-terminated string. */
444                         if (len < 0) {
445                                 if (c == '\0')
446                                         break;
447                                 /* Quote at most size - 1 bytes. */
448                                 if (i == size - 1)
449                                         continue;
450                         }
451                         if (!isprint(c) && !isspace(c)) {
452                                 usehex = 1;
453                                 break;
454                         }
455                 }
456         }
457
458         *s++ = '\"';
459
460         if (usehex) {
461                 /* Hex-quote the whole string. */
462                 for (i = 0; i < size; ++i) {
463                         c = ustr[i];
464                         /* Check for NUL-terminated string. */
465                         if (len < 0) {
466                                 if (c == '\0')
467                                         break;
468                                 /* Quote at most size - 1 bytes. */
469                                 if (i == size - 1)
470                                         continue;
471                         }
472                         sprintf(s, "\\x%02x", c);
473                         s += 4;
474                 }
475         } else {
476                 for (i = 0; i < size; ++i) {
477                         c = ustr[i];
478                         /* Check for NUL-terminated string. */
479                         if (len < 0) {
480                                 if (c == '\0')
481                                         break;
482                                 /* Quote at most size - 1 bytes. */
483                                 if (i == size - 1)
484                                         continue;
485                         }
486                         switch (c) {
487                                 case '\"': case '\\':
488                                         *s++ = '\\';
489                                         *s++ = c;
490                                         break;
491                                 case '\f':
492                                         *s++ = '\\';
493                                         *s++ = 'f';
494                                         break;
495                                 case '\n':
496                                         *s++ = '\\';
497                                         *s++ = 'n';
498                                         break;
499                                 case '\r':
500                                         *s++ = '\\';
501                                         *s++ = 'r';
502                                         break;
503                                 case '\t':
504                                         *s++ = '\\';
505                                         *s++ = 't';
506                                         break;
507                                 case '\v':
508                                         *s++ = '\\';
509                                         *s++ = 'v';
510                                         break;
511                                 default:
512                                         if (isprint(c))
513                                                 *s++ = c;
514                                         else if (i + 1 < size
515                                                  && isdigit(ustr[i + 1])) {
516                                                 sprintf(s, "\\%03o", c);
517                                                 s += 4;
518                                         } else {
519                                                 sprintf(s, "\\%o", c);
520                                                 s += strlen(s);
521                                         }
522                                         break;
523                         }
524                 }
525         }
526
527         *s++ = '\"';
528         *s = '\0';
529
530         /* Return nonzero if the string was unterminated.  */
531         return i == size;
532 }
533
534 /*
535  * Print path string specified by address `addr' and length `n'.
536  * If path length exceeds `n', append `...' to the output.
537  */
538 void
539 printpathn(struct tcb *tcp, long addr, int n)
540 {
541         if (!addr) {
542                 tprintf("NULL");
543                 return;
544         }
545
546         /* Cap path length to the path buffer size,
547            and NUL-terminate the buffer. */
548         if (n > sizeof path - 1)
549                 n = sizeof path - 1;
550         path[n] = '\0';
551
552         /* Fetch one byte more to find out whether path length > n. */
553         if (umovestr(tcp, addr, n + 1, path) < 0)
554                 tprintf("%#lx", addr);
555         else {
556                 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
557                 int trunc = (path[n] != '\0');
558
559                 if (trunc)
560                         path[n] = '\0';
561                 (void) string_quote(path, outstr, -1, n + 1);
562                 if (trunc)
563                         strcat(outstr, "...");
564                 tprintf("%s", outstr);
565         }
566 }
567
568 void
569 printpath(struct tcb *tcp, long addr)
570 {
571         printpathn(tcp, addr, sizeof path - 1);
572 }
573
574 /*
575  * Print string specified by address `addr' and length `len'.
576  * If `len' < 0, treat the string as a NUL-terminated string.
577  * If string length exceeds `max_strlen', append `...' to the output.
578  */
579 void
580 printstr(struct tcb *tcp, long addr, int len)
581 {
582         static char *str = NULL;
583         static char *outstr;
584         int size;
585
586         if (!addr) {
587                 tprintf("NULL");
588                 return;
589         }
590         /* Allocate static buffers if they are not allocated yet. */
591         if (!str)
592                 str = malloc(max_strlen + 1);
593         if (!outstr)
594                 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
595         if (!str || !outstr) {
596                 fprintf(stderr, "out of memory\n");
597                 tprintf("%#lx", addr);
598                 return;
599         }
600
601         if (len < 0) {
602                 /*
603                  * Treat as a NUL-terminated string: fetch one byte more
604                  * because string_quote() quotes one byte less.
605                  */
606                 size = max_strlen + 1;
607                 str[max_strlen] = '\0';
608                 if (umovestr(tcp, addr, size, str) < 0) {
609                         tprintf("%#lx", addr);
610                         return;
611                 }
612         }
613         else {
614                 size = MIN(len, max_strlen);
615                 if (umoven(tcp, addr, size, str) < 0) {
616                         tprintf("%#lx", addr);
617                         return;
618                 }
619         }
620
621         if (string_quote(str, outstr, len, size) &&
622             (len < 0 || len > max_strlen))
623                 strcat(outstr, "...");
624
625         tprintf("%s", outstr);
626 }
627
628 #if HAVE_SYS_UIO_H
629 void
630 dumpiov(struct tcb *tcp, int len, long addr)
631 {
632 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
633         union {
634                 struct { u_int32_t base; u_int32_t len; } *iov32;
635                 struct { u_int64_t base; u_int64_t len; } *iov64;
636         } iovu;
637 #define iov iovu.iov64
638 #define sizeof_iov \
639   (personality_wordsize[current_personality] == 4 \
640    ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
641 #define iov_iov_base(i) \
642   (personality_wordsize[current_personality] == 4 \
643    ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
644 #define iov_iov_len(i) \
645   (personality_wordsize[current_personality] == 4 \
646    ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
647 #else
648         struct iovec *iov;
649 #define sizeof_iov sizeof(*iov)
650 #define iov_iov_base(i) iov[i].iov_base
651 #define iov_iov_len(i) iov[i].iov_len
652 #endif
653         int i;
654         unsigned long size;
655
656         size = sizeof_iov * (unsigned long) len;
657         if (size / sizeof_iov != len
658             || (iov = malloc(size)) == NULL) {
659                 fprintf(stderr, "out of memory\n");
660                 return;
661         }
662         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
663                 for (i = 0; i < len; i++) {
664                         /* include the buffer number to make it easy to
665                          * match up the trace with the source */
666                         tprintf(" * %lu bytes in buffer %d\n",
667                                 (unsigned long)iov_iov_len(i), i);
668                         dumpstr(tcp, (long) iov_iov_base(i),
669                                 iov_iov_len(i));
670                 }
671         }
672         free((char *) iov);
673 #undef sizeof_iov
674 #undef iov_iov_base
675 #undef iov_iov_len
676 #undef iov
677 }
678 #endif
679
680 void
681 dumpstr(struct tcb *tcp, long addr, int len)
682 {
683         static int strsize = -1;
684         static unsigned char *str;
685         static char outstr[80];
686         char *s;
687         int i, j;
688
689         if (strsize < len) {
690                 if (str)
691                         free(str);
692                 if ((str = malloc(len)) == NULL) {
693                         fprintf(stderr, "out of memory\n");
694                         return;
695                 }
696                 strsize = len;
697         }
698
699         if (umoven(tcp, addr, len, (char *) str) < 0)
700                 return;
701
702         for (i = 0; i < len; i += 16) {
703                 s = outstr;
704                 sprintf(s, " | %05x ", i);
705                 s += 9;
706                 for (j = 0; j < 16; j++) {
707                         if (j == 8)
708                                 *s++ = ' ';
709                         if (i + j < len) {
710                                 sprintf(s, " %02x", str[i + j]);
711                                 s += 3;
712                         }
713                         else {
714                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
715                         }
716                 }
717                 *s++ = ' '; *s++ = ' ';
718                 for (j = 0; j < 16; j++) {
719                         if (j == 8)
720                                 *s++ = ' ';
721                         if (i + j < len) {
722                                 if (isprint(str[i + j]))
723                                         *s++ = str[i + j];
724                                 else
725                                         *s++ = '.';
726                         }
727                         else
728                                 *s++ = ' ';
729                 }
730                 tprintf("%s |\n", outstr);
731         }
732 }
733
734 #define PAGMASK (~(PAGSIZ - 1))
735 /*
736  * move `len' bytes of data from process `pid'
737  * at address `addr' to our space at `laddr'
738  */
739 int
740 umoven(struct tcb *tcp, long addr, int len, char *laddr)
741 {
742 #ifdef LINUX
743         int pid = tcp->pid;
744         int n, m;
745         int started = 0;
746         union {
747                 long val;
748                 char x[sizeof(long)];
749         } u;
750
751         if (addr & (sizeof(long) - 1)) {
752                 /* addr not a multiple of sizeof(long) */
753                 n = addr - (addr & -sizeof(long)); /* residue */
754                 addr &= -sizeof(long); /* residue */
755                 errno = 0;
756                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
757                 if (errno) {
758                         if (started && (errno==EPERM || errno==EIO)) {
759                                 /* Ran into 'end of memory' - stupid "printpath" */
760                                 return 0;
761                         }
762                         /* But if not started, we had a bogus address. */
763                         if (addr != 0 && errno != EIO && errno != ESRCH)
764                                 perror("ptrace: umoven");
765                         return -1;
766                 }
767                 started = 1;
768                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
769                 addr += sizeof(long), laddr += m, len -= m;
770         }
771         while (len) {
772                 errno = 0;
773                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
774                 if (errno) {
775                         if (started && (errno==EPERM || errno==EIO)) {
776                                 /* Ran into 'end of memory' - stupid "printpath" */
777                                 return 0;
778                         }
779                         if (addr != 0 && errno != EIO && errno != ESRCH)
780                                 perror("ptrace: umoven");
781                         return -1;
782                 }
783                 started = 1;
784                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
785                 addr += sizeof(long), laddr += m, len -= m;
786         }
787 #endif /* LINUX */
788
789 #ifdef SUNOS4
790         int pid = tcp->pid;
791         int n;
792
793         while (len) {
794                 n = MIN(len, PAGSIZ);
795                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
796                 if (ptrace(PTRACE_READDATA, pid,
797                            (char *) addr, len, laddr) < 0) {
798                         if (errno != ESRCH) {
799                                 perror("umoven: ptrace(PTRACE_READDATA, ...)");
800                                 abort();
801                         }
802                         return -1;
803                 }
804                 len -= n;
805                 addr += n;
806                 laddr += n;
807         }
808 #endif /* SUNOS4 */
809
810 #ifdef USE_PROCFS
811 #ifdef HAVE_MP_PROCFS
812         int fd = tcp->pfd_as;
813 #else
814         int fd = tcp->pfd;
815 #endif
816         lseek(fd, addr, SEEK_SET);
817         if (read(fd, laddr, len) == -1)
818                 return -1;
819 #endif /* USE_PROCFS */
820
821         return 0;
822 }
823
824 /*
825  * like `umove' but make the additional effort of looking
826  * for a terminating zero byte.
827  */
828 int
829 umovestr(struct tcb *tcp, long addr, int len, char *laddr)
830 {
831 #ifdef USE_PROCFS
832 #ifdef HAVE_MP_PROCFS
833         int fd = tcp->pfd_as;
834 #else
835         int fd = tcp->pfd;
836 #endif
837         /* Some systems (e.g. FreeBSD) can be upset if we read off the
838            end of valid memory,  avoid this by trying to read up
839            to page boundaries.  But we don't know what a page is (and
840            getpagesize(2) (if it exists) doesn't necessarily return
841            hardware page size).  Assume all pages >= 1024 (a-historical
842            I know) */
843
844         int page = 1024;        /* How to find this? */
845         int move = page - (addr & (page - 1));
846         int left = len;
847
848         lseek(fd, addr, SEEK_SET);
849
850         while (left) {
851                 if (move > left) move = left;
852                 if ((move = read(fd, laddr, move)) <= 0)
853                         return left != len ? 0 : -1;
854                 if (memchr(laddr, 0, move)) break;
855                 left -= move;
856                 laddr += move;
857                 addr += move;
858                 move = page;
859         }
860 #else /* !USE_PROCFS */
861         int started = 0;
862         int pid = tcp->pid;
863         int i, n, m;
864         union {
865                 long val;
866                 char x[sizeof(long)];
867         } u;
868
869         if (addr & (sizeof(long) - 1)) {
870                 /* addr not a multiple of sizeof(long) */
871                 n = addr - (addr & -sizeof(long)); /* residue */
872                 addr &= -sizeof(long); /* residue */
873                 errno = 0;
874                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
875                 if (errno) {
876                         if (started && (errno==EPERM || errno==EIO)) {
877                                 /* Ran into 'end of memory' - stupid "printpath" */
878                                 return 0;
879                         }
880                         if (addr != 0 && errno != EIO && errno != ESRCH)
881                                 perror("umovestr");
882                         return -1;
883                 }
884                 started = 1;
885                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n, len));
886                 while (n & (sizeof(long) - 1))
887                         if (u.x[n++] == '\0')
888                                 return 0;
889                 addr += sizeof(long), laddr += m, len -= m;
890         }
891         while (len) {
892                 errno = 0;
893                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
894                 if (errno) {
895                         if (started && (errno==EPERM || errno==EIO)) {
896                                 /* Ran into 'end of memory' - stupid "printpath" */
897                                 return 0;
898                         }
899                         if (addr != 0 && errno != EIO && errno != ESRCH)
900                                 perror("umovestr");
901                         return -1;
902                 }
903                 started = 1;
904                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
905                 for (i = 0; i < sizeof(long); i++)
906                         if (u.x[i] == '\0')
907                                 return 0;
908
909                 addr += sizeof(long), laddr += m, len -= m;
910         }
911 #endif /* !USE_PROCFS */
912         return 0;
913 }
914
915 #ifdef LINUX
916 # if !defined (SPARC) && !defined(SPARC64)
917 #  define PTRACE_WRITETEXT      101
918 #  define PTRACE_WRITEDATA      102
919 # endif /* !SPARC && !SPARC64 */
920 #endif /* LINUX */
921
922 #ifdef SUNOS4
923
924 static int
925 uload(int cmd, int pid, long addr, int len, char *laddr)
926 {
927         int peek, poke;
928         int n, m;
929         union {
930                 long val;
931                 char x[sizeof(long)];
932         } u;
933
934         if (cmd == PTRACE_WRITETEXT) {
935                 peek = PTRACE_PEEKTEXT;
936                 poke = PTRACE_POKETEXT;
937         }
938         else {
939                 peek = PTRACE_PEEKDATA;
940                 poke = PTRACE_POKEDATA;
941         }
942         if (addr & (sizeof(long) - 1)) {
943                 /* addr not a multiple of sizeof(long) */
944                 n = addr - (addr & -sizeof(long)); /* residue */
945                 addr &= -sizeof(long);
946                 errno = 0;
947                 u.val = ptrace(peek, pid, (char *) addr, 0);
948                 if (errno) {
949                         perror("uload: POKE");
950                         return -1;
951                 }
952                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
953                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
954                         perror("uload: POKE");
955                         return -1;
956                 }
957                 addr += sizeof(long), laddr += m, len -= m;
958         }
959         while (len) {
960                 if (len < sizeof(long))
961                         u.val = ptrace(peek, pid, (char *) addr, 0);
962                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
963                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
964                         perror("uload: POKE");
965                         return -1;
966                 }
967                 addr += sizeof(long), laddr += m, len -= m;
968         }
969         return 0;
970 }
971
972 int
973 tload(int pid, int addr, int len, char *laddr)
974 {
975         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
976 }
977
978 int
979 dload(int pid, int addr, int len, char *laddr)
980 {
981         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
982 }
983
984 #endif /* SUNOS4 */
985
986 #ifndef USE_PROCFS
987
988 int
989 upeek(struct tcb *tcp, long off, long *res)
990 {
991         long val;
992
993 # ifdef SUNOS4_KERNEL_ARCH_KLUDGE
994         {
995                 static int is_sun4m = -1;
996                 struct utsname name;
997
998                 /* Round up the usual suspects. */
999                 if (is_sun4m == -1) {
1000                         if (uname(&name) < 0) {
1001                                 perror("upeek: uname?");
1002                                 exit(1);
1003                         }
1004                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
1005                         if (is_sun4m) {
1006                                 const struct xlat *x;
1007
1008                                 for (x = struct_user_offsets; x->str; x++)
1009                                         x->val += 1024;
1010                         }
1011                 }
1012                 if (is_sun4m)
1013                         off += 1024;
1014         }
1015 # endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1016         errno = 0;
1017         val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1018         if (val == -1 && errno) {
1019                 if (errno != ESRCH) {
1020                         char buf[60];
1021                         sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1022                         perror(buf);
1023                 }
1024                 return -1;
1025         }
1026         *res = val;
1027         return 0;
1028 }
1029
1030 #endif /* !USE_PROCFS */
1031
1032 void
1033 printcall(struct tcb *tcp)
1034 {
1035 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1036                            sizeof(long) == 8 ? "[????????????????] " : \
1037                            NULL /* crash */)
1038
1039 #ifdef LINUX
1040 # ifdef I386
1041         long eip;
1042
1043         if (upeek(tcp, 4*EIP, &eip) < 0) {
1044                 PRINTBADPC;
1045                 return;
1046         }
1047         tprintf("[%08lx] ", eip);
1048
1049 # elif defined(S390) || defined(S390X)
1050         long psw;
1051         if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
1052                 PRINTBADPC;
1053                 return;
1054         }
1055 #  ifdef S390
1056         tprintf("[%08lx] ", psw);
1057 #  elif S390X
1058         tprintf("[%16lx] ", psw);
1059 #  endif
1060
1061 # elif defined(X86_64)
1062         long rip;
1063
1064         if (upeek(tcp, 8*RIP, &rip) < 0) {
1065                 PRINTBADPC;
1066                 return;
1067         }
1068         tprintf("[%16lx] ", rip);
1069 # elif defined(IA64)
1070         long ip;
1071
1072         if (upeek(tcp, PT_B0, &ip) < 0) {
1073                 PRINTBADPC;
1074                 return;
1075         }
1076         tprintf("[%08lx] ", ip);
1077 # elif defined(POWERPC)
1078         long pc;
1079
1080         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1081                 PRINTBADPC;
1082                 return;
1083         }
1084 #  ifdef POWERPC64
1085         tprintf("[%016lx] ", pc);
1086 #  else
1087         tprintf("[%08lx] ", pc);
1088 #  endif
1089 # elif defined(M68K)
1090         long pc;
1091
1092         if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1093                 tprintf("[????????] ");
1094                 return;
1095         }
1096         tprintf("[%08lx] ", pc);
1097 # elif defined(ALPHA)
1098         long pc;
1099
1100         if (upeek(tcp, REG_PC, &pc) < 0) {
1101                 tprintf("[????????????????] ");
1102                 return;
1103         }
1104         tprintf("[%08lx] ", pc);
1105 # elif defined(SPARC) || defined(SPARC64)
1106         struct pt_regs regs;
1107         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1108                 PRINTBADPC;
1109                 return;
1110         }
1111 #  if defined(SPARC64)
1112         tprintf("[%08lx] ", regs.tpc);
1113 #  else
1114         tprintf("[%08lx] ", regs.pc);
1115 #  endif
1116 # elif defined(HPPA)
1117         long pc;
1118
1119         if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1120                 tprintf("[????????] ");
1121                 return;
1122         }
1123         tprintf("[%08lx] ", pc);
1124 # elif defined(MIPS)
1125         long pc;
1126
1127         if (upeek(tcp, REG_EPC, &pc) < 0) {
1128                 tprintf("[????????] ");
1129                 return;
1130         }
1131         tprintf("[%08lx] ", pc);
1132 # elif defined(SH)
1133         long pc;
1134
1135         if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1136                 tprintf("[????????] ");
1137                 return;
1138         }
1139         tprintf("[%08lx] ", pc);
1140 # elif defined(SH64)
1141         long pc;
1142
1143         if (upeek(tcp, REG_PC, &pc) < 0) {
1144                 tprintf("[????????????????] ");
1145                 return;
1146         }
1147         tprintf("[%08lx] ", pc);
1148 # elif defined(ARM)
1149         long pc;
1150
1151         if (upeek(tcp, 4*15, &pc) < 0) {
1152                 PRINTBADPC;
1153                 return;
1154         }
1155         tprintf("[%08lx] ", pc);
1156 # elif defined(AVR32)
1157         long pc;
1158
1159         if (upeek(tcp, REG_PC, &pc) < 0) {
1160                 tprintf("[????????] ");
1161                 return;
1162         }
1163         tprintf("[%08lx] ", pc);
1164 # elif defined(BFIN)
1165         long pc;
1166
1167         if (upeek(tcp, PT_PC, &pc) < 0) {
1168                 PRINTBADPC;
1169                 return;
1170         }
1171         tprintf("[%08lx] ", pc);
1172 #elif defined(CRISV10)
1173         long pc;
1174
1175         if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1176                 PRINTBADPC;
1177                 return;
1178         }
1179         tprintf("[%08lx] ", pc);
1180 #elif defined(CRISV32)
1181         long pc;
1182
1183         if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1184                 PRINTBADPC;
1185                 return;
1186         }
1187         tprintf("[%08lx] ", pc);
1188 # endif /* architecture */
1189 #endif /* LINUX */
1190
1191 #ifdef SUNOS4
1192         struct regs regs;
1193
1194         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1195                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1196                 PRINTBADPC;
1197                 return;
1198         }
1199         tprintf("[%08x] ", regs.r_o7);
1200 #endif /* SUNOS4 */
1201
1202 #ifdef SVR4
1203         /* XXX */
1204         PRINTBADPC;
1205 #endif
1206
1207 #ifdef FREEBSD
1208         struct reg regs;
1209         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1210         tprintf("[%08x] ", regs.r_eip);
1211 #endif /* FREEBSD */
1212 }
1213
1214
1215 /*
1216  * These #if's are huge, please indent them correctly.
1217  * It's easy to get confused otherwise.
1218  */
1219 #ifndef USE_PROCFS
1220
1221 # ifdef LINUX
1222
1223 #  include "syscall.h"
1224
1225 #  include <sys/syscall.h>
1226 #  ifndef CLONE_PTRACE
1227 #   define CLONE_PTRACE    0x00002000
1228 #  endif
1229 #  ifndef CLONE_VFORK
1230 #   define CLONE_VFORK     0x00004000
1231 #  endif
1232 #  ifndef CLONE_VM
1233 #   define CLONE_VM        0x00000100
1234 #  endif
1235 #  ifndef CLONE_STOPPED
1236 #   define CLONE_STOPPED   0x02000000
1237 #  endif
1238
1239 #  ifdef IA64
1240
1241 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1242    subsystem has them for x86... */
1243 #   define SYS_fork     2
1244 #   define SYS_vfork    190
1245
1246 typedef unsigned long *arg_setup_state;
1247
1248 static int
1249 arg_setup(struct tcb *tcp, arg_setup_state *state)
1250 {
1251         unsigned long cfm, sof, sol;
1252         long bsp;
1253
1254         if (ia32) {
1255                 /* Satisfy a false GCC warning.  */
1256                 *state = NULL;
1257                 return 0;
1258         }
1259
1260         if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1261                 return -1;
1262         if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1263                 return -1;
1264
1265         sof = (cfm >> 0) & 0x7f;
1266         sol = (cfm >> 7) & 0x7f;
1267         bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1268
1269         *state = (unsigned long *) bsp;
1270         return 0;
1271 }
1272
1273 #   define arg_finish_change(tcp, state)        0
1274
1275 #   ifdef SYS_fork
1276 static int
1277 get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1278 {
1279         int ret;
1280
1281         if (ia32)
1282                 ret = upeek(tcp, PT_R11, valp);
1283         else
1284                 ret = umoven(tcp,
1285                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1286                               sizeof(long), (void *) valp);
1287         return ret;
1288 }
1289
1290 static int
1291 get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1292 {
1293         int ret;
1294
1295         if (ia32)
1296                 ret = upeek(tcp, PT_R9, valp);
1297         else
1298                 ret = umoven(tcp,
1299                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1300                               sizeof(long), (void *) valp);
1301         return ret;
1302 }
1303 #   endif
1304
1305 static int
1306 set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1307 {
1308         int req = PTRACE_POKEDATA;
1309         void *ap;
1310
1311         if (ia32) {
1312                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1313                 req = PTRACE_POKEUSER;
1314         } else
1315                 ap = ia64_rse_skip_regs(*state, 0);
1316         errno = 0;
1317         ptrace(req, tcp->pid, ap, val);
1318         return errno ? -1 : 0;
1319 }
1320
1321 static int
1322 set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1323 {
1324         int req = PTRACE_POKEDATA;
1325         void *ap;
1326
1327         if (ia32) {
1328                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1329                 req = PTRACE_POKEUSER;
1330         } else
1331                 ap = ia64_rse_skip_regs(*state, 1);
1332         errno = 0;
1333         ptrace(req, tcp->pid, ap, val);
1334         return errno ? -1 : 0;
1335 }
1336
1337 /* ia64 does not return the input arguments from functions (and syscalls)
1338    according to ia64 RSE (Register Stack Engine) behavior.  */
1339
1340 #   define restore_arg0(tcp, state, val) ((void) (state), 0)
1341 #   define restore_arg1(tcp, state, val) ((void) (state), 0)
1342
1343 #  elif defined (SPARC) || defined (SPARC64)
1344
1345 typedef struct pt_regs arg_setup_state;
1346
1347 #   define arg_setup(tcp, state) \
1348     (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1349 #   define arg_finish_change(tcp, state) \
1350     (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1351
1352 #   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1353 #   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1354 #   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1355 #   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1356 #   define restore_arg0(tcp, state, val) 0
1357
1358 #  else /* other architectures */
1359
1360 #   if defined S390 || defined S390X
1361 /* Note: this is only true for the `clone' system call, which handles
1362    arguments specially.  We could as well say that its first two arguments
1363    are swapped relative to other architectures, but that would just be
1364    another #ifdef in the calls.  */
1365 #    define arg0_offset PT_GPR3
1366 #    define arg1_offset PT_ORIGGPR2
1367 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1368 #    define restore_arg1(tcp, state, val) ((void) (state), 0)
1369 #    define arg0_index  1
1370 #    define arg1_index  0
1371 #   elif defined (ALPHA) || defined (MIPS)
1372 #    define arg0_offset REG_A0
1373 #    define arg1_offset (REG_A0+1)
1374 #   elif defined (AVR32)
1375 #    define arg0_offset (REG_R12)
1376 #    define arg1_offset (REG_R11)
1377 #   elif defined (POWERPC)
1378 #    define arg0_offset (sizeof(unsigned long)*PT_R3)
1379 #    define arg1_offset (sizeof(unsigned long)*PT_R4)
1380 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1381 #   elif defined (HPPA)
1382 #    define arg0_offset  PT_GR26
1383 #    define arg1_offset  (PT_GR26-4)
1384 #   elif defined (X86_64)
1385 #    define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1386 #    define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1387 #   elif defined (SH)
1388 #    define arg0_offset (4*(REG_REG0+4))
1389 #    define arg1_offset (4*(REG_REG0+5))
1390 #   elif defined (SH64)
1391     /* ABI defines arg0 & 1 in r2 & r3 */
1392 #    define arg0_offset   (REG_OFFSET+16)
1393 #    define arg1_offset   (REG_OFFSET+24)
1394 #    define restore_arg0(tcp, state, val) 0
1395 #   elif defined CRISV10 || defined CRISV32
1396 #    define arg0_offset   (4*PT_R11)
1397 #    define arg1_offset   (4*PT_ORIG_R10)
1398 #    define restore_arg0(tcp, state, val) 0
1399 #    define restore_arg1(tcp, state, val) 0
1400 #    define arg0_index   1
1401 #    define arg1_index   0
1402 #   else
1403 #    define arg0_offset 0
1404 #    define arg1_offset 4
1405 #    if defined ARM
1406 #     define restore_arg0(tcp, state, val) 0
1407 #    endif
1408 #   endif
1409
1410 typedef int arg_setup_state;
1411
1412 #   define arg_setup(tcp, state) (0)
1413 #   define arg_finish_change(tcp, state)        0
1414 #   define get_arg0(tcp, cookie, valp) \
1415     (upeek((tcp), arg0_offset, (valp)))
1416 #   define get_arg1(tcp, cookie, valp) \
1417     (upeek((tcp), arg1_offset, (valp)))
1418
1419 static int
1420 set_arg0(struct tcb *tcp, void *cookie, long val)
1421 {
1422         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1423 }
1424
1425 static int
1426 set_arg1(struct tcb *tcp, void *cookie, long val)
1427 {
1428         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1429 }
1430
1431 #  endif /* architectures */
1432
1433 #  ifndef restore_arg0
1434 #   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1435 #  endif
1436 #  ifndef restore_arg1
1437 #   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1438 #  endif
1439
1440 #  ifndef arg0_index
1441 #   define arg0_index 0
1442 #   define arg1_index 1
1443 #  endif
1444
1445 int
1446 setbpt(struct tcb *tcp)
1447 {
1448         static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1449         arg_setup_state state;
1450
1451         if (tcp->flags & TCB_BPTSET) {
1452                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1453                 return -1;
1454         }
1455
1456         /*
1457          * It's a silly kludge to initialize this with a search at runtime.
1458          * But it's better than maintaining another magic thing in the
1459          * godforsaken tables.
1460          */
1461         if (clone_scno[current_personality] == 0) {
1462                 int i;
1463                 for (i = 0; i < nsyscalls; ++i)
1464                         if (sysent[i].sys_func == sys_clone) {
1465                                 clone_scno[current_personality] = i;
1466                                 break;
1467                         }
1468         }
1469
1470         switch (known_scno(tcp)) {
1471 #  ifdef SYS_vfork
1472         case SYS_vfork:
1473 #  endif
1474 #  ifdef SYS_fork
1475         case SYS_fork:
1476 #  endif
1477 #  if defined SYS_fork || defined SYS_vfork
1478                 if (arg_setup(tcp, &state) < 0
1479                     || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1480                     || get_arg1(tcp, &state, &tcp->inst[1]) < 0
1481                     || change_syscall(tcp, clone_scno[current_personality]) < 0
1482                     || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1483                     || set_arg1(tcp, &state, 0) < 0
1484                     || arg_finish_change(tcp, &state) < 0)
1485                         return -1;
1486                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1487                 tcp->u_arg[arg1_index] = 0;
1488                 tcp->flags |= TCB_BPTSET;
1489                 return 0;
1490 #  endif
1491
1492         case SYS_clone: ;
1493 #  ifdef SYS_clone2
1494         case SYS_clone2: ;
1495 #  endif
1496                 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1497                    contrary to x86 SYS_vfork above.  Even on x86 we turn the
1498                    vfork semantics into plain fork - each application must not
1499                    depend on the vfork specifics according to POSIX.  We would
1500                    hang waiting for the parent resume otherwise.  We need to
1501                    clear also CLONE_VM but only in the CLONE_VFORK case as
1502                    otherwise we would break pthread_create.  */
1503
1504                 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1505                 if (new_arg0 & CLONE_VFORK)
1506                         new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1507                 if (arg_setup(tcp, &state) < 0
1508                  || set_arg0(tcp, &state, new_arg0) < 0
1509                  || arg_finish_change(tcp, &state) < 0)
1510                         return -1;
1511                 tcp->flags |= TCB_BPTSET;
1512                 tcp->inst[0] = tcp->u_arg[arg0_index];
1513                 tcp->inst[1] = tcp->u_arg[arg1_index];
1514                 return 0;
1515
1516         default:
1517                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1518                         tcp->scno, tcp->pid);
1519                 break;
1520         }
1521
1522         return -1;
1523 }
1524
1525 int
1526 clearbpt(struct tcb *tcp)
1527 {
1528         arg_setup_state state;
1529         if (arg_setup(tcp, &state) < 0
1530             || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1531             || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1532             || arg_finish_change(tcp, &state))
1533                 if (errno != ESRCH)
1534                         return -1;
1535         tcp->flags &= ~TCB_BPTSET;
1536         return 0;
1537 }
1538
1539 # else /* !defined LINUX */
1540
1541 int
1542 setbpt(struct tcb *tcp)
1543 {
1544 #  ifdef SUNOS4
1545 #   ifdef SPARC /* This code is slightly sparc specific */
1546
1547         struct regs regs;
1548 #    define BPT 0x91d02001      /* ta   1 */
1549 #    define LOOP        0x10800000      /* ba   0 */
1550 #    define LOOPA       0x30800000      /* ba,a 0 */
1551 #    define NOP 0x01000000
1552 #    if LOOPA
1553         static int loopdeloop[1] = {LOOPA};
1554 #    else
1555         static int loopdeloop[2] = {LOOP, NOP};
1556 #    endif
1557
1558         if (tcp->flags & TCB_BPTSET) {
1559                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1560                 return -1;
1561         }
1562         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1563                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1564                 return -1;
1565         }
1566         tcp->baddr = regs.r_o7 + 8;
1567         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1568                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1569                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1570                 return -1;
1571         }
1572
1573         /*
1574          * XXX - BRUTAL MODE ON
1575          * We cannot set a real BPT in the child, since it will not be
1576          * traced at the moment it will reach the trap and would probably
1577          * die with a core dump.
1578          * Thus, we are force our way in by taking out two instructions
1579          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1580          * generated by out PTRACE_ATTACH.
1581          * Of cause, if we evaporate ourselves in the middle of all this...
1582          */
1583         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1584                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1585                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1586                 return -1;
1587         }
1588         tcp->flags |= TCB_BPTSET;
1589
1590 #   endif /* SPARC */
1591 #  endif /* SUNOS4 */
1592
1593         return 0;
1594 }
1595
1596 int
1597 clearbpt(struct tcb *tcp)
1598 {
1599 #  ifdef SUNOS4
1600 #   ifdef SPARC
1601
1602 #    if !LOOPA
1603         struct regs regs;
1604 #    endif
1605
1606         if (!(tcp->flags & TCB_BPTSET)) {
1607                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1608                 return -1;
1609         }
1610         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1611                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1612                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1613                 return -1;
1614         }
1615         tcp->flags &= ~TCB_BPTSET;
1616
1617 #    if !LOOPA
1618         /*
1619          * Since we don't have a single instruction breakpoint, we may have
1620          * to adjust the program counter after removing our `breakpoint'.
1621          */
1622         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1623                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1624                 return -1;
1625         }
1626         if ((regs.r_pc < tcp->baddr) ||
1627                                 (regs.r_pc > tcp->baddr + 4)) {
1628                 /* The breakpoint has not been reached yet */
1629                 if (debug)
1630                         fprintf(stderr,
1631                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1632                                         regs.r_pc, tcp->baddr);
1633                 return 0;
1634         }
1635         if (regs.r_pc != tcp->baddr)
1636                 if (debug)
1637                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1638                                 regs.r_pc, tcp->baddr);
1639
1640         regs.r_pc = tcp->baddr;
1641         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1642                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1643                 return -1;
1644         }
1645 #    endif /* LOOPA */
1646 #   endif /* SPARC */
1647 #  endif /* SUNOS4 */
1648
1649         return 0;
1650 }
1651
1652 # endif /* !defined LINUX */
1653
1654 #endif /* !USE_PROCFS */
1655
1656
1657 #ifdef SUNOS4
1658
1659 static int
1660 getex(struct tcb *tcp, struct exec *hdr)
1661 {
1662         int n;
1663
1664         for (n = 0; n < sizeof *hdr; n += 4) {
1665                 long res;
1666                 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
1667                         return -1;
1668                 memcpy(((char *) hdr) + n, &res, 4);
1669         }
1670         if (debug) {
1671                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1672                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1673                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1674                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1675         }
1676         return 0;
1677 }
1678
1679 int
1680 fixvfork(struct tcb *tcp)
1681 {
1682         int pid = tcp->pid;
1683         /*
1684          * Change `vfork' in a freshly exec'ed dynamically linked
1685          * executable's (internal) symbol table to plain old `fork'
1686          */
1687
1688         struct exec hdr;
1689         struct link_dynamic dyn;
1690         struct link_dynamic_2 ld;
1691         char *strtab, *cp;
1692
1693         if (getex(tcp, &hdr) < 0)
1694                 return -1;
1695         if (!hdr.a_dynamic)
1696                 return -1;
1697
1698         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1699                 fprintf(stderr, "Cannot read DYNAMIC\n");
1700                 return -1;
1701         }
1702         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1703                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1704                 return -1;
1705         }
1706         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1707                 fprintf(stderr, "out of memory\n");
1708                 return -1;
1709         }
1710         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1711                                         (int)ld.ld_symb_size, strtab) < 0)
1712                 goto err;
1713
1714         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1715                 if (strcmp(cp, "_vfork") == 0) {
1716                         if (debug)
1717                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1718                         strcpy(cp, "_fork");
1719                         break;
1720                 }
1721                 cp += strlen(cp)+1;
1722         }
1723         if (cp < strtab + ld.ld_symb_size)
1724                 /*
1725                  * Write entire symbol table back to avoid
1726                  * memory alignment bugs in ptrace
1727                  */
1728                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1729                                         (int)ld.ld_symb_size, strtab) < 0)
1730                         goto err;
1731
1732         free(strtab);
1733         return 0;
1734
1735 err:
1736         free(strtab);
1737         return -1;
1738 }
1739
1740 #endif /* SUNOS4 */