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