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