]> granicus.if.org Git - strace/blob - util.c
.
[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)
82
83 # define fpq kernel_fpq
84 # define fq kernel_fq
85 # define fpu kernel_fpu
86 # include <asm/reg.h>
87 # undef fpq
88 # undef fq
89 # undef fpu
90
91 #if defined (SPARC64)
92 # define r_pc r_tpc
93 # undef PTRACE_GETREGS
94 # define PTRACE_GETREGS PTRACE_GETREGS64
95 # undef PTRACE_SETREGS
96 # define PTRACE_SETREGS PTRACE_SETREGS64
97 #endif /* SPARC64 */
98
99 #if !defined(__GLIBC__)
100
101 #include <linux/unistd.h>
102
103 #define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104           type5,arg5,syscall) \
105 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106 { \
107       long __res; \
108 \
109 __asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110                   "or %%g0, %2, %%o1\n\t" \
111                   "or %%g0, %3, %%o2\n\t" \
112                   "or %%g0, %4, %%o3\n\t" \
113                   "or %%g0, %5, %%o4\n\t" \
114                   "or %%g0, %6, %%g1\n\t" \
115 #if defined (SPARC64)
116                   "t 0x6d\n\t" \
117 #else
118                   "t 0x10\n\t" \
119 #endif
120                   "bcc 1f\n\t" \
121                   "or %%g0, %%o0, %0\n\t" \
122                   "sub %%g0, %%o0, %0\n\t" \
123                   "1:\n\t" \
124                   : "=r" (__res) \
125                   : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126                     "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127                     "i" (__NR_##syscall)  \
128                   : "g1", "o0", "o1", "o2", "o3", "o4"); \
129 if (__res>=0) \
130         return (type) __res; \
131 errno = -__res; \
132 return -1; \
133 }
134
135 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137 #define _ptrace
138
139 #endif
140
141 #endif
142
143 /* macros */
144 #ifndef MAX
145 #define MAX(a,b)                (((a) > (b)) ? (a) : (b))
146 #endif
147 #ifndef MIN
148 #define MIN(a,b)                (((a) < (b)) ? (a) : (b))
149 #endif
150
151 void
152 tv_tv(tv, a, b)
153 struct timeval *tv;
154 int a;
155 int b;
156 {
157         tv->tv_sec = a;
158         tv->tv_usec = b;
159 }
160
161 int
162 tv_nz(a)
163 struct timeval *a;
164 {
165         return a->tv_sec || a->tv_usec;
166 }
167
168 int
169 tv_cmp(a, b)
170 struct timeval *a, *b;
171 {
172         if (a->tv_sec < b->tv_sec
173             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174                 return -1;
175         if (a->tv_sec > b->tv_sec
176             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177                 return 1;
178         return 0;
179 }
180
181 double
182 tv_float(tv)
183 struct timeval *tv;
184 {
185         return tv->tv_sec + tv->tv_usec/1000000.0;
186 }
187
188 void
189 tv_add(tv, a, b)
190 struct timeval *tv, *a, *b;
191 {
192         tv->tv_sec = a->tv_sec + b->tv_sec;
193         tv->tv_usec = a->tv_usec + b->tv_usec;
194         if (tv->tv_usec > 1000000) {
195                 tv->tv_sec++;
196                 tv->tv_usec -= 1000000;
197         }
198 }
199
200 void
201 tv_sub(tv, a, b)
202 struct timeval *tv, *a, *b;
203 {
204         tv->tv_sec = a->tv_sec - b->tv_sec;
205         tv->tv_usec = a->tv_usec - b->tv_usec;
206         if (((long) tv->tv_usec) < 0) {
207                 tv->tv_sec--;
208                 tv->tv_usec += 1000000;
209         }
210 }
211
212 void
213 tv_div(tv, a, n)
214 struct timeval *tv, *a;
215 int n;
216 {
217         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219         tv->tv_usec %= 1000000;
220 }
221
222 void
223 tv_mul(tv, a, n)
224 struct timeval *tv, *a;
225 int n;
226 {
227         tv->tv_usec = a->tv_usec * n;
228         tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229         tv->tv_usec %= 1000000;
230 }
231
232 char *
233 xlookup(xlat, val)
234 const struct xlat *xlat;
235 int val;
236 {
237         for (; xlat->str != NULL; xlat++)
238                 if (xlat->val == val)
239                         return xlat->str;
240         return NULL;
241 }
242
243 /*
244  * Print entry in struct xlat table, if there.
245  */
246 void
247 printxval(xlat, val, dflt)
248 const struct xlat *xlat;
249 int val;
250 char *dflt;
251 {
252         char *str = xlookup(xlat, val);
253
254         if (str)
255                 tprintf("%s", str);
256         else
257                 tprintf("%#x /* %s */", val, dflt);
258 }
259
260 /*
261  * Interpret `xlat' as an array of flags
262  * print the entries whose bits are on in `flags'
263  * return # of flags printed.
264  */
265 int
266 addflags(xlat, flags)
267 const struct xlat *xlat;
268 int flags;
269 {
270         int n;
271
272         for (n = 0; xlat->str; xlat++) {
273                 if (xlat->val && (flags & xlat->val) == xlat->val) {
274                         tprintf("|%s", xlat->str);
275                         flags &= ~xlat->val;
276                         n++;
277                 }
278         }
279         if (flags) {
280                 tprintf("|%#x", flags);
281                 n++;
282         }
283         return n;
284 }
285
286 int
287 printflags(xlat, flags)
288 const struct xlat *xlat;
289 int flags;
290 {
291         int n;
292         char *sep;
293
294         if (flags == 0 && xlat->val == 0) {
295                 tprintf("%s", xlat->str);
296                 return 1;
297         }
298
299         sep = "";
300         for (n = 0; xlat->str; xlat++) {
301                 if (xlat->val && (flags & xlat->val) == xlat->val) {
302                         tprintf("%s%s", sep, xlat->str);
303                         flags &= ~xlat->val;
304                         sep = "|";
305                         n++;
306                 }
307         }
308         if (flags) {
309                 tprintf("%s%#x", sep, flags);
310                 n++;
311         }
312         return n;
313 }
314
315 void
316 printnum(tcp, addr, fmt)
317 struct tcb *tcp;
318 long addr;
319 char *fmt;
320 {
321         long num;
322
323         if (!addr) {
324                 tprintf("NULL");
325                 return;
326         }
327         if (umove(tcp, addr, &num) < 0) {
328                 tprintf("%#lx", addr);
329                 return;
330         }
331         tprintf("[");
332         tprintf(fmt, num);
333         tprintf("]");
334 }
335
336 void
337 printuid(text, uid)
338 const char *text;
339 unsigned long uid;
340 {
341         tprintf("%s", text);
342         tprintf((uid == -1) ? "%ld" : "%lu", uid);
343 }
344
345 static char path[MAXPATHLEN + 1];
346
347 void
348 string_quote(str)
349 char *str;
350 {
351         char buf[2 * MAXPATHLEN + 1];
352         char *s;
353
354         if (!strpbrk(str, "\"\'\\")) {
355                 tprintf("\"%s\"", str);
356                 return;
357         }
358         for (s = buf; *str; str++) {
359                 switch (*str) {
360                 case '\"': case '\'': case '\\':
361                         *s++ = '\\'; *s++ = *str; break;
362                 default:
363                         *s++ = *str; break;
364                 }
365         }
366         *s = '\0';
367         tprintf("\"%s\"", buf);
368 }
369
370 void
371 printpath(tcp, addr)
372 struct tcb *tcp;
373 long addr;
374 {
375         if (addr == 0)
376                 tprintf("NULL");
377         else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
378                 tprintf("%#lx", addr);
379         else
380                 string_quote(path);
381         return;
382 }
383
384 void
385 printpathn(tcp, addr, n)
386 struct tcb *tcp;
387 long addr;
388 int n;
389 {
390         if (addr == 0)
391                 tprintf("NULL");
392         else    if (umovestr(tcp, addr, n, path) < 0)
393                 tprintf("%#lx", addr);
394         else {
395                 path[n] = '\0';
396                 string_quote(path);
397         }
398 }
399
400 void
401 printstr(tcp, addr, len)
402 struct tcb *tcp;
403 long addr;
404 int len;
405 {
406         static unsigned char *str = NULL;
407         static char *outstr;
408         int i, n, c, usehex;
409         char *s, *outend;
410
411         if (!addr) {
412                 tprintf("NULL");
413                 return;
414         }
415         if (!str) {
416                 if ((str = malloc(max_strlen)) == NULL
417                     || (outstr = malloc(2*max_strlen)) == NULL) {
418                         fprintf(stderr, "printstr: no memory\n");
419                         tprintf("%#lx", addr);
420                         return;
421                 }
422         }
423         outend = outstr + max_strlen * 2 - 10;
424         if (len < 0) {
425                 n = max_strlen;
426                 if (umovestr(tcp, addr, n, (char *) str) < 0) {
427                         tprintf("%#lx", addr);
428                         return;
429                 }
430         }
431         else {
432                 n = MIN(len, max_strlen);
433                 if (umoven(tcp, addr, n, (char *) str) < 0) {
434                         tprintf("%#lx", addr);
435                         return;
436                 }
437         }
438
439         usehex = 0;
440         if (xflag > 1)
441                 usehex = 1;
442         else if (xflag) {
443                 for (i = 0; i < n; i++) {
444                         c = str[i];
445                         if (len < 0 && c == '\0')
446                                 break;
447                         if (!isprint(c) && !isspace(c)) {
448                                 usehex = 1;
449                                 break;
450                         }
451                 }
452         }
453
454         s = outstr;
455         *s++ = '\"';
456
457         if (usehex) {
458                 for (i = 0; i < n; i++) {
459                         c = str[i];
460                         if (len < 0 && c == '\0')
461                                 break;
462                         sprintf(s, "\\x%02x", c);
463                         s += 4;
464                         if (s > outend)
465                                 break;
466                 }
467         }
468         else {
469                 for (i = 0; i < n; i++) {
470                         c = str[i];
471                         if (len < 0 && c == '\0')
472                                 break;
473                         switch (c) {
474                         case '\"': case '\'': case '\\':
475                                 *s++ = '\\'; *s++ = c; break;
476                         case '\f':
477                                 *s++ = '\\'; *s++ = 'f'; break;
478                         case '\n':
479                                 *s++ = '\\'; *s++ = 'n'; break;
480                         case '\r':
481                                 *s++ = '\\'; *s++ = 'r'; break;
482                         case '\t':
483                                 *s++ = '\\'; *s++ = 't'; break;
484                         case '\v':
485                                 *s++ = '\\'; *s++ = 'v'; break;
486                         default:
487                                 if (isprint(c))
488                                         *s++ = c;
489                                 else if (i < n - 1 && isdigit(str[i + 1])) {
490                                         sprintf(s, "\\%03o", c);
491                                         s += 4;
492                                 }
493                                 else {
494                                         sprintf(s, "\\%o", c);
495                                         s += strlen(s);
496                                 }
497                                 break;
498                         }
499                         if (s > outend)
500                                 break;
501                 }
502         }
503
504         *s++ = '\"';
505         if (i < len || (len < 0 && (i == n || s > outend))) {
506                 *s++ = '.'; *s++ = '.'; *s++ = '.';
507         }
508         *s = '\0';
509         tprintf("%s", outstr);
510 }
511
512 #if HAVE_SYS_UIO_H
513 void
514 dumpiov(tcp, len, addr)
515 struct tcb * tcp;
516 int len;
517 long addr;
518 {
519         struct iovec *iov;
520         int i;
521
522
523         if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
524                 fprintf(stderr, "dump: No memory");
525                 return;
526         }
527         if (umoven(tcp, addr,
528                    len * sizeof *iov, (char *) iov) >= 0) {
529
530                 for (i = 0; i < len; i++) {
531                         /* include the buffer number to make it easy to
532                          * match up the trace with the source */
533                         tprintf(" * %lu bytes in buffer %d\n",
534                                 (unsigned long)iov[i].iov_len, i);
535                         dumpstr(tcp, (long) iov[i].iov_base,
536                                 iov[i].iov_len);
537                 }
538         }
539         free((char *) iov);
540
541 }
542 #endif
543
544 void
545 dumpstr(tcp, addr, len)
546 struct tcb *tcp;
547 long addr;
548 int len;
549 {
550         static int strsize = -1;
551         static unsigned char *str;
552         static char outstr[80];
553         char *s;
554         int i, j;
555
556         if (strsize < len) {
557                 if (str)
558                         free(str);
559                 if ((str = malloc(len)) == NULL) {
560                         fprintf(stderr, "dump: no memory\n");
561                         return;
562                 }
563                 strsize = len;
564         }
565
566         if (umoven(tcp, addr, len, (char *) str) < 0)
567                 return;
568
569         for (i = 0; i < len; i += 16) {
570                 s = outstr;
571                 sprintf(s, " | %05x ", i);
572                 s += 9;
573                 for (j = 0; j < 16; j++) {
574                         if (j == 8)
575                                 *s++ = ' ';
576                         if (i + j < len) {
577                                 sprintf(s, " %02x", str[i + j]);
578                                 s += 3;
579                         }
580                         else {
581                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
582                         }
583                 }
584                 *s++ = ' '; *s++ = ' ';
585                 for (j = 0; j < 16; j++) {
586                         if (j == 8)
587                                 *s++ = ' ';
588                         if (i + j < len) {
589                                 if (isprint(str[i + j]))
590                                         *s++ = str[i + j];
591                                 else
592                                         *s++ = '.';
593                         }
594                         else
595                                 *s++ = ' ';
596                 }
597                 tprintf("%s |\n", outstr);
598         }
599 }
600
601 #define PAGMASK (~(PAGSIZ - 1))
602 /*
603  * move `len' bytes of data from process `pid'
604  * at address `addr' to our space at `laddr'
605  */
606 int
607 umoven(tcp, addr, len, laddr)
608 struct tcb *tcp;
609 long addr;
610 int len;
611 char *laddr;
612 {
613
614 #ifdef LINUX
615         int pid = tcp->pid;
616         int n, m;
617         int started = 0;
618         union {
619                 long val;
620                 char x[sizeof(long)];
621         } u;
622
623         if (addr & (sizeof(long) - 1)) {
624                 /* addr not a multiple of sizeof(long) */
625                 n = addr - (addr & -sizeof(long)); /* residue */
626                 addr &= -sizeof(long); /* residue */
627                 errno = 0;
628                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
629                 if (errno) {
630                         if (started && (errno==EPERM || errno==EIO)) {
631                                 /* Ran into 'end of memory' - stupid "printpath" */
632                                 return 0;
633                         }
634                         /* But if not started, we had a bogus address. */
635                         perror("ptrace: umoven");
636                         return -1;
637                 }
638                 started = 1;
639                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
640                 addr += sizeof(long), laddr += m, len -= m;
641         }
642         while (len) {
643                 errno = 0;
644                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
645                 if (errno) {
646                         if (started && (errno==EPERM || errno==EIO)) {
647                                 /* Ran into 'end of memory' - stupid "printpath" */
648                                 return 0;
649                         }
650                         if (addr != 0)
651                                 perror("ptrace: umoven");
652                         return -1;
653                 }
654                 started = 1;
655                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
656                 addr += sizeof(long), laddr += m, len -= m;
657         }
658 #endif /* LINUX */
659
660 #ifdef SUNOS4
661         int pid = tcp->pid;
662 #if 0
663         int n, m;
664         union {
665                 long val;
666                 char x[sizeof(long)];
667         } u;
668
669         if (addr & (sizeof(long) - 1)) {
670                 /* addr not a multiple of sizeof(long) */
671                 n = addr - (addr & -sizeof(long)); /* residue */
672                 addr &= -sizeof(long); /* residue */
673                 errno = 0;
674                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
675                 if (errno) {
676                         perror("umoven");
677                         return -1;
678                 }
679                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
680                 addr += sizeof(long), laddr += m, len -= m;
681         }
682         while (len) {
683                 errno = 0;
684                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
685                 if (errno) {
686                         perror("umoven");
687                         return -1;
688                 }
689                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
690                 addr += sizeof(long), laddr += m, len -= m;
691         }
692 #else /* !oldway */
693         int n;
694
695         while (len) {
696                 n = MIN(len, PAGSIZ);
697                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
698                 if (ptrace(PTRACE_READDATA, pid,
699                            (char *) addr, len, laddr) < 0) {
700                         perror("umoven: ptrace(PTRACE_READDATA, ...)");
701                         abort();
702                         return -1;
703                 }
704                 len -= n;
705                 addr += n;
706                 laddr += n;
707         }
708 #endif /* !oldway */
709 #endif /* SUNOS4 */
710
711 #ifdef USE_PROCFS
712 #ifdef HAVE_MP_PROCFS
713         int fd = tcp->pfd_as;
714 #else
715         int fd = tcp->pfd;
716 #endif
717         lseek(fd, addr, SEEK_SET);
718         if (read(fd, laddr, len) == -1)
719                 return -1;
720 #endif /* USE_PROCFS */
721
722         return 0;
723 }
724
725 /*
726  * like `umove' but make the additional effort of looking
727  * for a terminating zero byte.
728  */
729 int
730 umovestr(tcp, addr, len, laddr)
731 struct tcb *tcp;
732 long addr;
733 int len;
734 char *laddr;
735 {
736 #ifdef USE_PROCFS
737 #ifdef HAVE_MP_PROCFS
738         int fd = tcp->pfd_as;
739 #else
740         int fd = tcp->pfd;
741 #endif
742         /* Some systems (e.g. FreeBSD) can be upset if we read off the
743            end of valid memory,  avoid this by trying to read up
744            to page boundaries.  But we don't know what a page is (and
745            getpagesize(2) (if it exists) doesn't necessarily return
746            hardware page size).  Assume all pages >= 1024 (a-historical
747            I know) */
748
749         int page = 1024;        /* How to find this? */
750         int move = page - (addr & (page - 1));
751         int left = len;
752
753         lseek(fd, addr, SEEK_SET);
754
755         while (left) {
756                 if (move > left) move = left;
757                 if ((move = read(fd, laddr, move)) <= 0)
758                         return left != len ? 0 : -1;
759                 if (memchr (laddr, 0, move)) break;
760                 left -= move;
761                 laddr += move;
762                 addr += move;
763                 move = page;
764         }
765 #else /* !USE_PROCFS */
766         int started = 0;
767         int pid = tcp->pid;
768         int i, n, m;
769         union {
770                 long val;
771                 char x[sizeof(long)];
772         } u;
773
774         if (addr & (sizeof(long) - 1)) {
775                 /* addr not a multiple of sizeof(long) */
776                 n = addr - (addr & -sizeof(long)); /* residue */
777                 addr &= -sizeof(long); /* residue */
778                 errno = 0;
779                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
780                 if (errno) {
781                         if (started && (errno==EPERM || errno==EIO)) {
782                                 /* Ran into 'end of memory' - stupid "printpath" */
783                                 return 0;
784                         }
785                         perror("umovestr");
786                         return -1;
787                 }
788                 started = 1;
789                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
790                 while (n & (sizeof(long) - 1))
791                         if (u.x[n++] == '\0')
792                                 return 0;
793                 addr += sizeof(long), laddr += m, len -= m;
794         }
795         while (len) {
796                 errno = 0;
797                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
798                 if (errno) {
799                         if (started && (errno==EPERM || errno==EIO)) {
800                                 /* Ran into 'end of memory' - stupid "printpath" */
801                                 return 0;
802                         }
803                         perror("umovestr");
804                         return -1;
805                 }
806                 started = 1;
807                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
808                 for (i = 0; i < sizeof(long); i++)
809                         if (u.x[i] == '\0')
810                                 return 0;
811
812                 addr += sizeof(long), laddr += m, len -= m;
813         }
814 #endif /* !USE_PROCFS */
815         return 0;
816 }
817
818 #ifdef LINUX
819 #if !defined (SPARC) && !defined(SPARC64)
820 #define PTRACE_WRITETEXT        101
821 #define PTRACE_WRITEDATA        102
822 #endif /* !SPARC && !SPARC64 */
823 #endif /* LINUX */
824
825 #ifdef SUNOS4
826
827 static int
828 uload(cmd, pid, addr, len, laddr)
829 int cmd;
830 int pid;
831 long addr;
832 int len;
833 char *laddr;
834 {
835 #if 0
836         int n;
837
838         while (len) {
839                 n = MIN(len, PAGSIZ);
840                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
841                 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
842                         perror("uload: ptrace(PTRACE_WRITE, ...)");
843                         return -1;
844                 }
845                 len -= n;
846                 addr += n;
847                 laddr += n;
848         }
849 #else
850         int peek, poke;
851         int n, m;
852         union {
853                 long val;
854                 char x[sizeof(long)];
855         } u;
856
857         if (cmd == PTRACE_WRITETEXT) {
858                 peek = PTRACE_PEEKTEXT;
859                 poke = PTRACE_POKETEXT;
860         }
861         else {
862                 peek = PTRACE_PEEKDATA;
863                 poke = PTRACE_POKEDATA;
864         }
865         if (addr & (sizeof(long) - 1)) {
866                 /* addr not a multiple of sizeof(long) */
867                 n = addr - (addr & -sizeof(long)); /* residue */
868                 addr &= -sizeof(long);
869                 errno = 0;
870                 u.val = ptrace(peek, pid, (char *) addr, 0);
871                 if (errno) {
872                         perror("uload: POKE");
873                         return -1;
874                 }
875                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
876                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
877                         perror("uload: POKE");
878                         return -1;
879                 }
880                 addr += sizeof(long), laddr += m, len -= m;
881         }
882         while (len) {
883                 if (len < sizeof(long))
884                         u.val = ptrace(peek, pid, (char *) addr, 0);
885                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
886                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
887                         perror("uload: POKE");
888                         return -1;
889                 }
890                 addr += sizeof(long), laddr += m, len -= m;
891         }
892 #endif
893         return 0;
894 }
895
896 int
897 tload(pid, addr, len, laddr)
898 int pid;
899 int addr, len;
900 char *laddr;
901 {
902         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
903 }
904
905 int
906 dload(pid, addr, len, laddr)
907 int pid;
908 int addr;
909 int len;
910 char *laddr;
911 {
912         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
913 }
914
915 #endif /* SUNOS4 */
916
917 #ifndef USE_PROCFS
918
919 int
920 upeek(pid, off, res)
921 int pid;
922 long off;
923 long *res;
924 {
925         long val;
926
927 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
928         {
929                 static int is_sun4m = -1;
930                 struct utsname name;
931
932                 /* Round up the usual suspects. */
933                 if (is_sun4m == -1) {
934                         if (uname(&name) < 0) {
935                                 perror("upeek: uname?");
936                                 exit(1);
937                         }
938                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
939                         if (is_sun4m) {
940                                 extern const struct xlat struct_user_offsets[];
941                                 const struct xlat *x;
942
943                                 for (x = struct_user_offsets; x->str; x++)
944                                         x->val += 1024;
945                         }
946                 }
947                 if (is_sun4m)
948                         off += 1024;
949         }
950 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
951         errno = 0;
952         val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
953         if (val == -1 && errno) {
954                 char buf[60];
955                 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
956                 perror(buf);
957                 return -1;
958         }
959         *res = val;
960         return 0;
961 }
962
963 #endif /* !USE_PROCFS */
964
965 long
966 getpc(tcp)
967 struct tcb *tcp;
968 {
969
970 #ifdef LINUX
971         long pc;
972 #if defined(I386)
973         if (upeek(tcp->pid, 4*EIP, &pc) < 0)
974                 return -1;
975 #elif defined(X86_64)
976         if (upeek(tcp->pid, 8*RIP, &pc) < 0)
977                 return -1;
978 #elif defined(IA64)
979         if (upeek(tcp->pid, PT_B0, &pc) < 0)
980                 return -1;
981 #elif defined(ARM)
982         if (upeek(tcp->pid, 4*15, &pc) < 0)
983                 return -1;
984 #elif defined(POWERPC)
985         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
986                 return -1;
987 #elif defined(M68k)
988         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
989                 return -1;
990 #elif defined(ALPHA)
991         if (upeek(tcp->pid, REG_PC, &pc) < 0)
992                 return -1;
993 #elif defined(MIPS)
994         if (upeek(tcp->pid, REG_EPC, &pc) < 0)
995                 return -1;
996 #elif defined(SPARC) || defined(SPARC64)
997         struct regs regs;
998         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
999                 return -1;
1000         pc = regs.r_pc;
1001 #elif defined(S390) || defined(S390X)
1002         if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1003                 return -1;
1004 #elif defined(HPPA)
1005         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1006                 return -1;
1007 #elif defined(SH)
1008        if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1009                return -1;
1010 #elif defined(SH64)
1011        if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1012                return -1;
1013 #endif
1014         return pc;
1015 #endif /* LINUX */
1016
1017 #ifdef SUNOS4
1018         /*
1019          * Return current program counter for `pid'
1020          * Assumes PC is never 0xffffffff
1021          */
1022         struct regs regs;
1023
1024         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1025                 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1026                 return -1;
1027         }
1028         return regs.r_pc;
1029 #endif /* SUNOS4 */
1030
1031 #ifdef SVR4
1032         /* XXX */
1033         return 0;
1034 #endif /* SVR4 */
1035
1036 #ifdef FREEBSD
1037         struct reg regs;
1038         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1039         return regs.r_eip;
1040 #endif /* FREEBSD */
1041 }
1042
1043 void
1044 printcall(tcp)
1045 struct tcb *tcp;
1046 {
1047 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1048                            sizeof(long) == 8 ? "[????????????????] " : \
1049                            NULL /* crash */)
1050
1051 #ifdef LINUX
1052 #ifdef I386
1053         long eip;
1054
1055         if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1056                 PRINTBADPC;
1057                 return;
1058         }
1059         tprintf("[%08lx] ", eip);
1060
1061 #elif defined(S390) || defined(S390X)
1062          long psw;
1063          if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1064                  PRINTBADPC;
1065                  return;
1066          }
1067 #ifdef S390
1068          tprintf("[%08lx] ", psw);
1069 #elif S390X
1070        tprintf("[%16lx] ", psw);
1071 #endif
1072
1073 #elif defined(X86_64)
1074         long rip;
1075
1076         if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1077                 PRINTBADPC;
1078                 return;
1079         }
1080         tprintf("[%16lx] ", rip);
1081 #elif defined(IA64)
1082         long ip;
1083
1084         if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1085                 PRINTBADPC;
1086                 return;
1087         }
1088         tprintf("[%08lx] ", ip);
1089 #elif defined(POWERPC)
1090         long pc;
1091
1092         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1093                 tprintf ("[????????] ");
1094                 return;
1095         }
1096         tprintf("[%08lx] ", pc);
1097 #elif defined(M68k)
1098         long pc;
1099
1100         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1101                 tprintf ("[????????] ");
1102                 return;
1103         }
1104         tprintf("[%08lx] ", pc);
1105 #elif defined(ALPHA)
1106         long pc;
1107
1108         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1109                 tprintf ("[????????????????] ");
1110                 return;
1111         }
1112         tprintf("[%08lx] ", pc);
1113 #elif defined(SPARC) || defined(SPARC64)
1114         struct regs regs;
1115         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1116                 PRINTBADPC;
1117                 return;
1118         }
1119         tprintf("[%08lx] ", regs.r_pc);
1120 #elif defined(HPPA)
1121         long pc;
1122
1123         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1124                 tprintf ("[????????] ");
1125                 return;
1126         }
1127         tprintf("[%08lx] ", pc);
1128 #elif defined(MIPS)
1129         long pc;
1130
1131         if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1132                 tprintf ("[????????] ");
1133                 return;
1134         }
1135         tprintf("[%08lx] ", pc);
1136 #elif defined(SH)
1137        long pc;
1138
1139        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1140                tprintf ("[????????] ");
1141                return;
1142        }
1143        tprintf("[%08lx] ", pc);
1144 #elif defined(SH64)
1145         long pc;
1146
1147         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1148                 tprintf ("[????????????????] ");
1149                 return;
1150         }
1151         tprintf("[%08lx] ", pc);
1152 #elif defined(ARM)
1153         long pc;
1154
1155         if (upeek(tcp->pid, 4*15, &pc) < 0) {
1156                 PRINTBADPC;
1157                 return;
1158         }
1159         tprintf("[%08lx] ", pc);
1160 #endif /* !architecture */
1161 #endif /* LINUX */
1162
1163 #ifdef SUNOS4
1164         struct regs regs;
1165
1166         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1167                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1168                 PRINTBADPC;
1169                 return;
1170         }
1171         tprintf("[%08x] ", regs.r_o7);
1172 #endif /* SUNOS4 */
1173
1174 #ifdef SVR4
1175         /* XXX */
1176         PRINTBADPC;
1177 #endif
1178
1179 #ifdef FREEBSD
1180         struct reg regs;
1181         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1182         tprintf("[%08x] ", regs.r_eip);
1183 #endif /* FREEBSD */
1184 }
1185
1186 #ifndef USE_PROCFS
1187
1188 #if defined LINUX
1189
1190 #include <sys/syscall.h>
1191 #ifndef CLONE_PTRACE
1192 # define CLONE_PTRACE    0x00002000
1193 #endif
1194
1195 #ifdef IA64
1196
1197 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1198    subsystem has them for x86... */
1199 #define SYS_fork        2
1200 #define SYS_vfork       190
1201
1202 typedef unsigned long *arg_setup_state;
1203
1204 static int
1205 arg_setup(struct tcb *tcp, arg_setup_state *state)
1206 {
1207         unsigned long *bsp, cfm, sof, sol;
1208
1209         if (ia32)
1210                 return 0;
1211
1212         if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1213                 return -1;
1214         if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1215                 return -1;
1216
1217         sof = (cfm >> 0) & 0x7f;
1218         sol = (cfm >> 7) & 0x7f;
1219         bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1220
1221         *state = bsp;
1222         return 0;
1223 }
1224
1225 # define arg_finish_change(tcp, state)  0
1226
1227 #ifdef SYS_fork
1228 static int
1229 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1230 {
1231         int ret;
1232
1233         if (ia32)
1234                 ret = upeek (tcp->pid, PT_R11, valp);
1235         else
1236                 ret = umoven (tcp,
1237                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1238                               sizeof(long), (void *) valp);
1239         return ret;
1240 }
1241
1242 static int
1243 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1244 {
1245         int ret;
1246
1247         if (ia32)
1248                 ret = upeek (tcp->pid, PT_R9, valp);
1249         else
1250                 ret = umoven (tcp,
1251                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1252                               sizeof(long), (void *) valp);
1253         return ret;
1254 }
1255 #endif
1256
1257 static int
1258 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1259 {
1260         int req = PTRACE_POKEDATA;
1261         void *ap;
1262
1263         if (ia32) {
1264                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1265                 req = PTRACE_POKEUSER;
1266         } else
1267                 ap = ia64_rse_skip_regs(*state, 0);
1268         errno = 0;
1269         ptrace(req, tcp->pid, ap, val);
1270         return errno ? -1 : 0;
1271 }
1272
1273 static int
1274 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1275 {
1276         int req = PTRACE_POKEDATA;
1277         void *ap;
1278
1279         if (ia32) {
1280                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1281                 req = PTRACE_POKEUSER;
1282         } else
1283                 ap = ia64_rse_skip_regs(*state, 1);
1284         errno = 0;
1285         ptrace(req, tcp->pid, ap, val);
1286         return errno ? -1 : 0;
1287 }
1288
1289 #elif defined (SPARC) || defined (SPARC64)
1290
1291 typedef struct regs arg_setup_state;
1292
1293 # define arg_setup(tcp, state) \
1294   (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1295 # define arg_finish_change(tcp, state) \
1296   (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1297
1298 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1299 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1300 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1301 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1302 # define restore_arg0(tcp, state, val) 0
1303
1304 #else
1305
1306 # if defined S390 || defined S390X
1307 /* Note: this is only true for the `clone' system call, which handles
1308    arguments specially.  We could as well say that its first two arguments
1309    are swapped relative to other architectures, but that would just be
1310    another #ifdef in the calls.  */
1311 #  define arg0_offset   PT_GPR3
1312 #  define arg1_offset   PT_ORIGGPR2
1313 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1314 #  define restore_arg1(tcp, state, val) ((void) (state), 0)
1315 #  define arg0_index    1
1316 #  define arg1_index    0
1317 # elif defined (ALPHA) || defined (MIPS)
1318 #  define arg0_offset   REG_A0
1319 #  define arg1_offset   (REG_A0+1)
1320 # elif defined (POWERPC)
1321 #  define arg0_offset   (sizeof(unsigned long)*PT_R3)
1322 #  define arg1_offset   (sizeof(unsigned long)*PT_R4)
1323 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1324 # elif defined (HPPA)
1325 #  define arg0_offset    PT_GR26
1326 #  define arg1_offset    (PT_GR26-4)
1327 # elif defined (X86_64)
1328 #  define arg0_offset   ((long)(8*(current_personality ? RBX : RDI)))
1329 #  define arg1_offset   ((long)(8*(current_personality ? RCX : RSI)))
1330 # elif defined (SH)
1331 #  define arg0_offset   (4*(REG_REG0+4))
1332 #  define arg1_offset   (4*(REG_REG0+5))
1333 # elif defined (SH64)
1334    /* ABI defines arg0 & 1 in r2 & r3 */
1335 #  define arg0_offset   (REG_OFFSET+16)
1336 #  define arg1_offset   (REG_OFFSET+24)
1337 #  define restore_arg0(tcp, state, val) 0
1338 # else
1339 #  define arg0_offset   0
1340 #  define arg1_offset   4
1341 #  if defined ARM
1342 #   define restore_arg0(tcp, state, val) 0
1343 #  endif
1344 # endif
1345
1346 typedef int arg_setup_state;
1347
1348 # define arg_setup(tcp, state) (0)
1349 # define arg_finish_change(tcp, state)  0
1350 # define get_arg0(tcp, cookie, valp) \
1351   (upeek ((tcp)->pid, arg0_offset, (valp)))
1352 # define get_arg1(tcp, cookie, valp) \
1353   (upeek ((tcp)->pid, arg1_offset, (valp)))
1354
1355 static int
1356 set_arg0 (struct tcb *tcp, void *cookie, long val)
1357 {
1358         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1359 }
1360
1361 static int
1362 set_arg1 (struct tcb *tcp, void *cookie, long val)
1363 {
1364         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1365 }
1366
1367 #endif
1368
1369 #ifndef restore_arg0
1370 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1371 #endif
1372 #ifndef restore_arg1
1373 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1374 #endif
1375
1376 #ifndef arg0_index
1377 # define arg0_index 0
1378 # define arg1_index 1
1379 #endif
1380
1381 int
1382 setbpt(tcp)
1383 struct tcb *tcp;
1384 {
1385         extern int change_syscall(struct tcb *, int);
1386         arg_setup_state state;
1387
1388         if (tcp->flags & TCB_BPTSET) {
1389                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1390                 return -1;
1391         }
1392
1393         switch (tcp->scno) {
1394 #ifdef SYS_vfork
1395         case SYS_vfork:
1396 #endif
1397 #ifdef SYS_fork
1398         case SYS_fork:
1399 #endif
1400 #if defined SYS_fork || defined SYS_vfork
1401                 if (arg_setup (tcp, &state) < 0
1402                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1403                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1404                     || change_syscall(tcp, SYS_clone) < 0
1405                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1406                     || set_arg1 (tcp, &state, 0) < 0
1407                     || arg_finish_change (tcp, &state) < 0)
1408                         return -1;
1409                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1410                 tcp->u_arg[arg1_index] = 0;
1411                 tcp->flags |= TCB_BPTSET;
1412                 return 0;
1413 #endif
1414
1415         case SYS_clone:
1416 #ifdef SYS_clone2
1417         case SYS_clone2:
1418 #endif
1419                 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1420                     && (arg_setup (tcp, &state) < 0
1421                         || set_arg0 (tcp, &state,
1422                                      tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1423                         || arg_finish_change (tcp, &state) < 0))
1424                         return -1;
1425                 tcp->flags |= TCB_BPTSET;
1426                 tcp->inst[0] = tcp->u_arg[arg0_index];
1427                 tcp->inst[1] = tcp->u_arg[arg1_index];
1428                 return 0;
1429
1430         default:
1431                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1432                         tcp->scno, tcp->pid);
1433                 break;
1434         }
1435
1436         return -1;
1437 }
1438
1439 int
1440 clearbpt(tcp)
1441 struct tcb *tcp;
1442 {
1443         arg_setup_state state;
1444         if (arg_setup (tcp, &state) < 0
1445             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1446             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1447             || arg_finish_change (tcp, &state))
1448                 return -1;
1449         tcp->flags &= ~TCB_BPTSET;
1450         return 0;
1451 }
1452
1453 #else
1454
1455 int
1456 setbpt(tcp)
1457 struct tcb *tcp;
1458 {
1459
1460 #ifdef LINUX
1461 #if defined (SPARC) || defined (SPARC64)
1462         /* We simply use the SunOS breakpoint code. */
1463
1464         struct regs regs;
1465         unsigned long inst;
1466 #define LOOPA   0x30800000      /* ba,a 0 */
1467
1468         if (tcp->flags & TCB_BPTSET) {
1469                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1470                 return -1;
1471         }
1472         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1473                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1474                 return -1;
1475         }
1476         tcp->baddr = regs.r_o7 + 8;
1477         errno = 0;
1478         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1479         if(errno) {
1480                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1481                 return -1;
1482         }
1483
1484         /*
1485          * XXX - BRUTAL MODE ON
1486          * We cannot set a real BPT in the child, since it will not be
1487          * traced at the moment it will reach the trap and would probably
1488          * die with a core dump.
1489          * Thus, we are force our way in by taking out two instructions
1490          * and insert an eternal loop instead, in expectance of the SIGSTOP
1491          * generated by out PTRACE_ATTACH.
1492          * Of cause, if we evaporate ourselves in the middle of all this...
1493          */
1494         errno = 0;
1495         inst = LOOPA;
1496 #if defined (SPARC64)
1497         inst <<= 32;
1498         inst |= (tcp->inst[0] & 0xffffffffUL);
1499 #endif
1500         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1501         if(errno) {
1502                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1503                 return -1;
1504         }
1505         tcp->flags |= TCB_BPTSET;
1506
1507 #else /* !SPARC && !SPARC64 */
1508 #ifdef IA64
1509         if (ia32) {
1510 #               define LOOP     0x0000feeb
1511                 if (tcp->flags & TCB_BPTSET) {
1512                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1513                                 tcp->pid);
1514                         return -1;
1515                 }
1516                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1517                         return -1;
1518                 if (debug)
1519                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1520                                 tcp->pid, tcp->baddr);
1521                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1522                                       (char *) tcp->baddr, 0);
1523                 if (errno) {
1524                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1525                         return -1;
1526                 }
1527                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1528                 if (errno) {
1529                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1530                         return -1;
1531                 }
1532                 tcp->flags |= TCB_BPTSET;
1533         } else {
1534                 /*
1535                  * Our strategy here is to replace the bundle that
1536                  * contained the clone() syscall with a bundle of the
1537                  * form:
1538                  *
1539                  *      { 1: br 1b; br 1b; br 1b }
1540                  *
1541                  * This ensures that the newly forked child will loop
1542                  * endlessly until we've got a chance to attach to it.
1543                  */
1544 #               define LOOP0    0x0000100000000017
1545 #               define LOOP1    0x4000000000200000
1546                 unsigned long addr, ipsr;
1547                 pid_t pid;
1548
1549                 pid = tcp->pid;
1550                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1551                         return -1;
1552                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1553                         return -1;
1554                 /* store "ri" in low two bits */
1555                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1556
1557                 errno = 0;
1558                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1559                                       0);
1560                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1561                                       0);
1562                 if (errno) {
1563                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1564                         return -1;
1565                 }
1566
1567                 errno = 0;
1568                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1569                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1570                 if (errno) {
1571                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1572                         return -1;
1573                 }
1574                 tcp->flags |= TCB_BPTSET;
1575         }
1576 #else /* !IA64 */
1577
1578 #if defined (I386) || defined(X86_64)
1579 #define LOOP    0x0000feeb
1580 #elif defined (M68K)
1581 #define LOOP    0x60fe0000
1582 #elif defined (ALPHA)
1583 #define LOOP    0xc3ffffff
1584 #elif defined (POWERPC)
1585 #define LOOP    0x48000000
1586 #elif defined(ARM)
1587 #define LOOP    0xEAFFFFFE
1588 #elif defined(MIPS)
1589 #define LOOP    0x1000ffff
1590 #elif defined(S390)
1591 #define LOOP    0xa7f40000      /* BRC 15,0 */
1592 #elif defined(S390X)
1593 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1594 #elif defined(HPPA)
1595 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1596 #elif defined(SH)
1597 #ifdef __LITTLE_ENDIAN__
1598 #define LOOP   0x0000affe
1599 #else
1600 #define LOOP   0xfeaf0000
1601 #endif
1602 #else
1603 #error unknown architecture
1604 #endif
1605
1606         if (tcp->flags & TCB_BPTSET) {
1607                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1608                 return -1;
1609         }
1610 #if defined (I386)
1611         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1612                 return -1;
1613 #elif defined (X86_64)
1614         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1615                 return -1;
1616 #elif defined (M68K)
1617         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1618           return -1;
1619 #elif defined (ALPHA)
1620         return -1;
1621 #elif defined (ARM)
1622         return -1;
1623 #elif defined (MIPS)
1624         return -1;              /* FIXME: I do not know what i do - Flo */
1625 #elif defined (POWERPC)
1626         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1627                 return -1;
1628 #elif defined(S390) || defined(S390X)
1629         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1630                 return -1;
1631 #elif defined(HPPA)
1632         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1633                 return -1;
1634         tcp->baddr &= ~0x03;
1635 #elif defined(SH)
1636        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1637                return -1;
1638 #else
1639 #error unknown architecture
1640 #endif
1641         if (debug)
1642                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1643         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1644         if (errno) {
1645                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1646                 return -1;
1647         }
1648         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1649         if (errno) {
1650                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1651                 return -1;
1652         }
1653         tcp->flags |= TCB_BPTSET;
1654
1655 #endif /* !IA64 */
1656 #endif /* SPARC || SPARC64 */
1657 #endif /* LINUX */
1658
1659 #ifdef SUNOS4
1660 #ifdef SPARC    /* This code is slightly sparc specific */
1661
1662         struct regs regs;
1663 #define BPT     0x91d02001      /* ta   1 */
1664 #define LOOP    0x10800000      /* ba   0 */
1665 #define LOOPA   0x30800000      /* ba,a 0 */
1666 #define NOP     0x01000000
1667 #if LOOPA
1668         static int loopdeloop[1] = {LOOPA};
1669 #else
1670         static int loopdeloop[2] = {LOOP, NOP};
1671 #endif
1672
1673         if (tcp->flags & TCB_BPTSET) {
1674                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1675                 return -1;
1676         }
1677         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1678                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1679                 return -1;
1680         }
1681         tcp->baddr = regs.r_o7 + 8;
1682         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1683                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1684                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1685                 return -1;
1686         }
1687
1688         /*
1689          * XXX - BRUTAL MODE ON
1690          * We cannot set a real BPT in the child, since it will not be
1691          * traced at the moment it will reach the trap and would probably
1692          * die with a core dump.
1693          * Thus, we are force our way in by taking out two instructions
1694          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1695          * generated by out PTRACE_ATTACH.
1696          * Of cause, if we evaporate ourselves in the middle of all this...
1697          */
1698         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1699                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1700                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1701                 return -1;
1702         }
1703         tcp->flags |= TCB_BPTSET;
1704
1705 #endif /* SPARC */
1706 #endif /* SUNOS4 */
1707
1708         return 0;
1709 }
1710
1711 int
1712 clearbpt(tcp)
1713 struct tcb *tcp;
1714 {
1715
1716 #ifdef LINUX
1717 #if defined(I386) || defined(X86_64)
1718         long eip;
1719 #elif defined(POWERPC)
1720         long pc;
1721 #elif defined(M68K)
1722         long pc;
1723 #elif defined(ALPHA)
1724         long pc;
1725 #elif defined(HPPA)
1726         long iaoq;
1727 #elif defined(SH)
1728        long pc;
1729 #endif /* architecture */
1730
1731 #if defined (SPARC) || defined (SPARC64)
1732         /* Again, we borrow the SunOS breakpoint code. */
1733         if (!(tcp->flags & TCB_BPTSET)) {
1734                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1735                 return -1;
1736         }
1737         errno = 0;
1738         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1739         if(errno) {
1740                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1741                 return -1;
1742         }
1743         tcp->flags &= ~TCB_BPTSET;
1744 #elif defined(IA64)
1745         if (ia32) {
1746                 unsigned long addr;
1747
1748                 if (debug)
1749                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1750                 if (!(tcp->flags & TCB_BPTSET)) {
1751                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1752                         return -1;
1753                 }
1754                 errno = 0;
1755                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1756                 if (errno) {
1757                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1758                         return -1;
1759                 }
1760                 tcp->flags &= ~TCB_BPTSET;
1761
1762                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1763                         return -1;
1764                 if (addr != tcp->baddr) {
1765                         /* The breakpoint has not been reached yet.  */
1766                         if (debug)
1767                                 fprintf(stderr,
1768                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1769                                                 addr, tcp->baddr);
1770                         return 0;
1771                 }
1772         } else {
1773                 unsigned long addr, ipsr;
1774                 pid_t pid;
1775
1776                 pid = tcp->pid;
1777
1778                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1779                         return -1;
1780                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1781                         return -1;
1782
1783                 /* restore original bundle: */
1784                 errno = 0;
1785                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1786                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1787                 if (errno) {
1788                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1789                         return -1;
1790                 }
1791
1792                 /* restore original "ri" in ipsr: */
1793                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1794                 errno = 0;
1795                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1796                 if (errno) {
1797                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1798                         return -1;
1799                 }
1800
1801                 tcp->flags &= ~TCB_BPTSET;
1802
1803                 if (addr != (tcp->baddr & ~0x3)) {
1804                         /* the breakpoint has not been reached yet.  */
1805                         if (debug)
1806                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1807                                         addr, tcp->baddr);
1808                         return 0;
1809                 }
1810         }
1811 #else /* !IA64  && !SPARC && !SPARC64 */
1812
1813         if (debug)
1814                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1815         if (!(tcp->flags & TCB_BPTSET)) {
1816                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1817                 return -1;
1818         }
1819         errno = 0;
1820         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1821         if (errno) {
1822                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1823                 return -1;
1824         }
1825         tcp->flags &= ~TCB_BPTSET;
1826
1827 #ifdef I386
1828         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1829                 return -1;
1830         if (eip != tcp->baddr) {
1831                 /* The breakpoint has not been reached yet.  */
1832                 if (debug)
1833                         fprintf(stderr,
1834                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1835                                         eip, tcp->baddr);
1836                 return 0;
1837         }
1838 #elif defined(X86_64)
1839         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1840                 return -1;
1841         if (eip != tcp->baddr) {
1842                 /* The breakpoint has not been reached yet.  */
1843                 if (debug)
1844                         fprintf(stderr,
1845                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1846                                         eip, tcp->baddr);
1847                 return 0;
1848         }
1849 #elif defined(POWERPC)
1850         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1851                 return -1;
1852         if (pc != tcp->baddr) {
1853                 /* The breakpoint has not been reached yet.  */
1854                 if (debug)
1855                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856                                 pc, tcp->baddr);
1857                 return 0;
1858         }
1859 #elif defined(M68K)
1860         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1861                 return -1;
1862         if (pc != tcp->baddr) {
1863                 /* The breakpoint has not been reached yet.  */
1864                 if (debug)
1865                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1866                                 pc, tcp->baddr);
1867                 return 0;
1868         }
1869 #elif defined(ALPHA)
1870         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1871                 return -1;
1872         if (pc != tcp->baddr) {
1873                 /* The breakpoint has not been reached yet.  */
1874                 if (debug)
1875                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1876                                 pc, tcp->baddr);
1877                 return 0;
1878         }
1879 #elif defined(HPPA)
1880         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1881                 return -1;
1882         iaoq &= ~0x03;
1883         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1884                 /* The breakpoint has not been reached yet.  */
1885                 if (debug)
1886                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1887                                 iaoq, tcp->baddr);
1888                 return 0;
1889         }
1890         iaoq = tcp->baddr | 3;
1891         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1892          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1893          * has no significant effect.
1894          */
1895         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1896         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1897 #elif defined(SH)
1898        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1899                return -1;
1900         if (pc != tcp->baddr) {
1901                 /* The breakpoint has not been reached yet.  */
1902                 if (debug)
1903                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1904                                 pc, tcp->baddr);
1905                 return 0;
1906         }
1907
1908 #endif /* arch */
1909 #endif /* !SPARC && !SPARC64 && !IA64 */
1910 #endif /* LINUX */
1911
1912 #ifdef SUNOS4
1913 #ifdef SPARC
1914
1915 #if !LOOPA
1916         struct regs regs;
1917 #endif
1918
1919         if (!(tcp->flags & TCB_BPTSET)) {
1920                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1921                 return -1;
1922         }
1923         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1924                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1925                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1926                 return -1;
1927         }
1928         tcp->flags &= ~TCB_BPTSET;
1929
1930 #if !LOOPA
1931         /*
1932          * Since we don't have a single instruction breakpoint, we may have
1933          * to adjust the program counter after removing the our `breakpoint'.
1934          */
1935         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1936                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1937                 return -1;
1938         }
1939         if ((regs.r_pc < tcp->baddr) ||
1940                                 (regs.r_pc > tcp->baddr + 4)) {
1941                 /* The breakpoint has not been reached yet */
1942                 if (debug)
1943                         fprintf(stderr,
1944                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1945                                         regs.r_pc, tcp->parent->baddr);
1946                 return 0;
1947         }
1948         if (regs.r_pc != tcp->baddr)
1949                 if (debug)
1950                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1951                                 regs.r_pc, tcp->baddr);
1952
1953         regs.r_pc = tcp->baddr;
1954         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1955                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1956                 return -1;
1957         }
1958 #endif /* LOOPA */
1959 #endif /* SPARC */
1960 #endif /* SUNOS4 */
1961
1962         return 0;
1963 }
1964
1965 #endif
1966
1967 #endif /* !USE_PROCFS */
1968
1969 #ifdef SUNOS4
1970
1971 static int
1972 getex(pid, hdr)
1973 int pid;
1974 struct exec *hdr;
1975 {
1976         int n;
1977
1978         for (n = 0; n < sizeof *hdr; n += 4) {
1979                 long res;
1980                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1981                         return -1;
1982                 memcpy(((char *) hdr) + n, &res, 4);
1983         }
1984         if (debug) {
1985                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1986                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1987                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1988                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1989         }
1990         return 0;
1991 }
1992
1993 int
1994 fixvfork(tcp)
1995 struct tcb *tcp;
1996 {
1997         int pid = tcp->pid;
1998         /*
1999          * Change `vfork' in a freshly exec'ed dynamically linked
2000          * executable's (internal) symbol table to plain old `fork'
2001          */
2002
2003         struct exec hdr;
2004         struct link_dynamic dyn;
2005         struct link_dynamic_2 ld;
2006         char *strtab, *cp;
2007
2008         if (getex(pid, &hdr) < 0)
2009                 return -1;
2010         if (!hdr.a_dynamic)
2011                 return -1;
2012
2013         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2014                 fprintf(stderr, "Cannot read DYNAMIC\n");
2015                 return -1;
2016         }
2017         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2018                 fprintf(stderr, "Cannot read link_dynamic_2\n");
2019                 return -1;
2020         }
2021         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2022                 fprintf(stderr, "fixvfork: out of memory\n");
2023                 return -1;
2024         }
2025         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2026                                         (int)ld.ld_symb_size, strtab) < 0)
2027                 goto err;
2028
2029 #if 0
2030         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2031                 fprintf(stderr, "[symbol: %s]\n", cp);
2032                 cp += strlen(cp)+1;
2033         }
2034         return 0;
2035 #endif
2036         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2037                 if (strcmp(cp, "_vfork") == 0) {
2038                         if (debug)
2039                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2040                         strcpy(cp, "_fork");
2041                         break;
2042                 }
2043                 cp += strlen(cp)+1;
2044         }
2045         if (cp < strtab + ld.ld_symb_size)
2046                 /*
2047                  * Write entire symbol table back to avoid
2048                  * memory alignment bugs in ptrace
2049                  */
2050                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2051                                         (int)ld.ld_symb_size, strtab) < 0)
2052                         goto err;
2053
2054         free(strtab);
2055         return 0;
2056
2057 err:
2058         free(strtab);
2059         return -1;
2060 }
2061
2062 #endif /* SUNOS4 */