util.c revision 1d08dcf46dd4b2cfe3e27723c05b0aec9955c591
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 <sys/user.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#if HAVE_SYS_UIO_H
42#include <sys/uio.h>
43#endif
44#ifdef SUNOS4
45#include <machine/reg.h>
46#include <a.out.h>
47#include <link.h>
48#endif /* SUNOS4 */
49
50#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
51#include <linux/ptrace.h>
52#endif
53
54#if defined(LINUX) && defined(IA64)
55#include <asm/ptrace_offsets.h>
56#endif
57
58#ifdef HAVE_SYS_REG_H
59#include <sys/reg.h>
60# define PTRACE_PEEKUSR PTRACE_PEEKUSER
61#elif defined(HAVE_LINUX_PTRACE_H)
62#undef PTRACE_SYSCALL
63#include <linux/ptrace.h>
64#endif
65
66#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
67#include <sys/utsname.h>
68#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
69
70#if defined(LINUX) && defined(SPARC)
71
72#include <asm/reg.h>
73
74#if !defined(__GLIBC__)
75
76#include <linux/unistd.h>
77
78#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
79          type5,arg5,syscall) \
80type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
81{ \
82      long __res; \
83\
84__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
85                  "or %%g0, %2, %%o1\n\t" \
86                  "or %%g0, %3, %%o2\n\t" \
87                  "or %%g0, %4, %%o3\n\t" \
88                  "or %%g0, %5, %%o4\n\t" \
89                  "or %%g0, %6, %%g1\n\t" \
90                  "t 0x10\n\t" \
91                  "bcc 1f\n\t" \
92                  "or %%g0, %%o0, %0\n\t" \
93                  "sub %%g0, %%o0, %0\n\t" \
94                  "1:\n\t" \
95                  : "=r" (__res) \
96                  : "0" ((long)(arg1)),"1" ((long)(arg2)), \
97                    "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
98                    "i" (__NR_##syscall)  \
99                  : "g1", "o0", "o1", "o2", "o3", "o4"); \
100if (__res>=0) \
101        return (type) __res; \
102errno = -__res; \
103return -1; \
104}
105
106static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
107
108#define _ptrace
109
110#endif
111
112#endif
113
114/* macros */
115#ifndef MAX
116#define MAX(a,b)		(((a) > (b)) ? (a) : (b))
117#endif
118#ifndef MIN
119#define MIN(a,b)		(((a) < (b)) ? (a) : (b))
120#endif
121
122void
123tv_tv(tv, a, b)
124struct timeval *tv;
125int a;
126int b;
127{
128	tv->tv_sec = a;
129	tv->tv_usec = b;
130}
131
132int
133tv_nz(a)
134struct timeval *a;
135{
136	return a->tv_sec || a->tv_usec;
137}
138
139int
140tv_cmp(a, b)
141struct timeval *a, *b;
142{
143	if (a->tv_sec < b->tv_sec
144	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
145		return -1;
146	if (a->tv_sec > b->tv_sec
147	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
148		return 1;
149	return 0;
150}
151
152double
153tv_float(tv)
154struct timeval *tv;
155{
156	return tv->tv_sec + tv->tv_usec/1000000.0;
157}
158
159void
160tv_add(tv, a, b)
161struct timeval *tv, *a, *b;
162{
163	tv->tv_sec = a->tv_sec + b->tv_sec;
164	tv->tv_usec = a->tv_usec + b->tv_usec;
165	if (tv->tv_usec > 1000000) {
166		tv->tv_sec++;
167		tv->tv_usec -= 1000000;
168	}
169}
170
171void
172tv_sub(tv, a, b)
173struct timeval *tv, *a, *b;
174{
175	tv->tv_sec = a->tv_sec - b->tv_sec;
176	tv->tv_usec = a->tv_usec - b->tv_usec;
177	if (((long) tv->tv_usec) < 0) {
178		tv->tv_sec--;
179		tv->tv_usec += 1000000;
180	}
181}
182
183void
184tv_div(tv, a, n)
185struct timeval *tv, *a;
186int n;
187{
188	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
189	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
190	tv->tv_usec %= 1000000;
191}
192
193void
194tv_mul(tv, a, n)
195struct timeval *tv, *a;
196int n;
197{
198	tv->tv_usec = a->tv_usec * n;
199	tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
200	tv->tv_usec %= 1000000;
201}
202
203char *
204xlookup(xlat, val)
205struct xlat *xlat;
206int val;
207{
208	for (; xlat->str != NULL; xlat++)
209		if (xlat->val == val)
210			return xlat->str;
211	return NULL;
212}
213
214/*
215 * Print entry in struct xlat table, if there.
216 */
217void
218printxval(xlat, val, dflt)
219struct xlat *xlat;
220int val;
221char *dflt;
222{
223	char *str = xlookup(xlat, val);
224
225	if (str)
226		tprintf("%s", str);
227	else
228		tprintf("%#x /* %s */", val, dflt);
229}
230
231/*
232 * Interpret `xlat' as an array of flags
233 * print the entries whose bits are on in `flags'
234 * return # of flags printed.
235 */
236int
237addflags(xlat, flags)
238struct xlat *xlat;
239int flags;
240{
241	int n;
242
243	for (n = 0; xlat->str; xlat++) {
244		if (xlat->val && (flags & xlat->val) == xlat->val) {
245			tprintf("|%s", xlat->str);
246			flags &= ~xlat->val;
247			n++;
248		}
249	}
250	if (flags) {
251		tprintf("|%#x", flags);
252		n++;
253	}
254	return n;
255}
256
257int
258printflags(xlat, flags)
259struct xlat *xlat;
260int flags;
261{
262	int n;
263	char *sep;
264
265	if (flags == 0 && xlat->val == 0) {
266		tprintf("%s", xlat->str);
267		return 1;
268	}
269
270	sep = "";
271	for (n = 0; xlat->str; xlat++) {
272		if (xlat->val && (flags & xlat->val) == xlat->val) {
273			tprintf("%s%s", sep, xlat->str);
274			flags &= ~xlat->val;
275			sep = "|";
276			n++;
277		}
278	}
279	if (flags) {
280		tprintf("%s%#x", sep, flags);
281		n++;
282	}
283	return n;
284}
285
286void
287printnum(tcp, addr, fmt)
288struct tcb *tcp;
289long addr;
290char *fmt;
291{
292	int num;
293
294	if (!addr) {
295		tprintf("NULL");
296		return;
297	}
298	if (umove(tcp, addr, &num) < 0) {
299		tprintf("%#lx", addr);
300		return;
301	}
302	tprintf("[");
303	tprintf(fmt, num);
304	tprintf("]");
305}
306
307static char path[MAXPATHLEN + 1];
308
309void
310string_quote(str)
311char *str;
312{
313	char buf[2 * MAXPATHLEN + 1];
314	char *s;
315
316	if (!strpbrk(str, "\"\'\\")) {
317		tprintf("\"%s\"", str);
318		return;
319	}
320	for (s = buf; *str; str++) {
321		switch (*str) {
322		case '\"': case '\'': case '\\':
323			*s++ = '\\'; *s++ = *str; break;
324		default:
325			*s++ = *str; break;
326		}
327	}
328	*s = '\0';
329	tprintf("\"%s\"", buf);
330}
331
332void
333printpath(tcp, addr)
334struct tcb *tcp;
335long addr;
336{
337	if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
338		tprintf("%#lx", addr);
339	else
340		string_quote(path);
341	return;
342}
343
344void
345printpathn(tcp, addr, n)
346struct tcb *tcp;
347long addr;
348int n;
349{
350	if (umovestr(tcp, addr, n, path) < 0)
351		tprintf("%#lx", addr);
352	else {
353		path[n] = '\0';
354		string_quote(path);
355	}
356}
357
358void
359printstr(tcp, addr, len)
360struct tcb *tcp;
361long addr;
362int len;
363{
364	static unsigned char *str = NULL;
365	static char *outstr;
366	int i, n, c, usehex;
367	char *s, *outend;
368
369	if (!addr) {
370		tprintf("NULL");
371		return;
372	}
373	if (!str) {
374		if ((str = malloc(max_strlen)) == NULL
375		    || (outstr = malloc(2*max_strlen)) == NULL) {
376			fprintf(stderr, "printstr: no memory\n");
377			tprintf("%#lx", addr);
378			return;
379		}
380	}
381	outend = outstr + max_strlen * 2 - 10;
382	if (len < 0) {
383		n = max_strlen;
384		if (umovestr(tcp, addr, n, (char *) str) < 0) {
385			tprintf("%#lx", addr);
386			return;
387		}
388	}
389	else {
390		n = MIN(len, max_strlen);
391		if (umoven(tcp, addr, n, (char *) str) < 0) {
392			tprintf("%#lx", addr);
393			return;
394		}
395	}
396
397	usehex = 0;
398	if (xflag > 1)
399		usehex = 1;
400	else if (xflag) {
401		for (i = 0; i < n; i++) {
402			c = str[i];
403			if (len < 0 && c == '\0')
404				break;
405			if (!isprint(c) && !isspace(c)) {
406				usehex = 1;
407				break;
408			}
409		}
410	}
411
412	s = outstr;
413	*s++ = '\"';
414
415	if (usehex) {
416		for (i = 0; i < n; i++) {
417			c = str[i];
418			if (len < 0 && c == '\0')
419				break;
420			sprintf(s, "\\x%02x", c);
421			s += 4;
422			if (s > outend)
423				break;
424		}
425	}
426	else {
427		for (i = 0; i < n; i++) {
428			c = str[i];
429			if (len < 0 && c == '\0')
430				break;
431			switch (c) {
432			case '\"': case '\'': case '\\':
433				*s++ = '\\'; *s++ = c; break;
434			case '\f':
435				*s++ = '\\'; *s++ = 'f'; break;
436			case '\n':
437				*s++ = '\\'; *s++ = 'n'; break;
438			case '\r':
439				*s++ = '\\'; *s++ = 'r'; break;
440			case '\t':
441				*s++ = '\\'; *s++ = 't'; break;
442			case '\v':
443				*s++ = '\\'; *s++ = 'v'; break;
444			default:
445				if (isprint(c))
446					*s++ = c;
447				else if (i < n - 1 && isdigit(str[i + 1])) {
448					sprintf(s, "\\%03o", c);
449					s += 4;
450				}
451				else {
452					sprintf(s, "\\%o", c);
453					s += strlen(s);
454				}
455				break;
456			}
457			if (s > outend)
458				break;
459		}
460	}
461
462	*s++ = '\"';
463	if (i < len || (len < 0 && (i == n || s > outend))) {
464		*s++ = '.'; *s++ = '.'; *s++ = '.';
465	}
466	*s = '\0';
467	tprintf("%s", outstr);
468}
469
470#if HAVE_SYS_UIO_H
471void
472dumpiov(tcp, len, addr)
473struct tcb * tcp;
474int len;
475long addr;
476{
477	struct iovec *iov;
478	int i;
479
480
481	if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
482		fprintf(stderr, "dump: No memory");
483		return;
484	}
485	if (umoven(tcp, addr,
486		   len * sizeof *iov, (char *) iov) >= 0) {
487
488		for (i = 0; i < len; i++) {
489                        /* include the buffer number to make it easy to
490                         * match up the trace with the source */
491                        tprintf(" * %lu bytes in buffer %d\n",
492                                (unsigned long)iov[i].iov_len, i);
493                        dumpstr(tcp, (long) iov[i].iov_base,
494                                iov[i].iov_len);
495                }
496	}
497	free((char *) iov);
498
499}
500#endif
501
502void
503dumpstr(tcp, addr, len)
504struct tcb *tcp;
505long addr;
506int len;
507{
508	static int strsize = -1;
509	static unsigned char *str;
510	static char outstr[80];
511	char *s;
512	int i, j;
513
514	if (strsize < len) {
515		if (str)
516			free(str);
517		if ((str = malloc(len)) == NULL) {
518			fprintf(stderr, "dump: no memory\n");
519			return;
520		}
521		strsize = len;
522	}
523
524	if (umoven(tcp, addr, len, (char *) str) < 0)
525		return;
526
527	for (i = 0; i < len; i += 16) {
528		s = outstr;
529		sprintf(s, " | %05x ", i);
530		s += 9;
531		for (j = 0; j < 16; j++) {
532			if (j == 8)
533				*s++ = ' ';
534			if (i + j < len) {
535				sprintf(s, " %02x", str[i + j]);
536				s += 3;
537			}
538			else {
539				*s++ = ' '; *s++ = ' '; *s++ = ' ';
540			}
541		}
542		*s++ = ' '; *s++ = ' ';
543		for (j = 0; j < 16; j++) {
544			if (j == 8)
545				*s++ = ' ';
546			if (i + j < len) {
547				if (isprint(str[i + j]))
548					*s++ = str[i + j];
549				else
550					*s++ = '.';
551			}
552			else
553				*s++ = ' ';
554		}
555		tprintf("%s |\n", outstr);
556	}
557}
558
559#define PAGMASK	(~(PAGSIZ - 1))
560/*
561 * move `len' bytes of data from process `pid'
562 * at address `addr' to our space at `laddr'
563 */
564int
565umoven(tcp, addr, len, laddr)
566struct tcb *tcp;
567long addr;
568int len;
569char *laddr;
570{
571
572#ifdef LINUX
573	int pid = tcp->pid;
574	int n, m;
575	int started = 0;
576	union {
577		long val;
578		char x[sizeof(long)];
579	} u;
580
581	if (addr & (sizeof(long) - 1)) {
582		/* addr not a multiple of sizeof(long) */
583		n = addr - (addr & -sizeof(long)); /* residue */
584		addr &= -sizeof(long); /* residue */
585		errno = 0;
586		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
587		if (errno) {
588			if (started && (errno==EPERM || errno==EIO)) {
589				/* Ran into 'end of memory' - stupid "printpath" */
590				return 0;
591			}
592			/* But if not started, we had a bogus address. */
593			perror("ptrace: umoven");
594			return -1;
595		}
596		started = 1;
597		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
598		addr += sizeof(long), laddr += m, len -= m;
599	}
600	while (len) {
601		errno = 0;
602		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
603		if (errno) {
604			if (started && (errno==EPERM || errno==EIO)) {
605				/* Ran into 'end of memory' - stupid "printpath" */
606				return 0;
607			}
608			perror("ptrace: umoven");
609			return -1;
610		}
611		started = 1;
612		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
613		addr += sizeof(long), laddr += m, len -= m;
614	}
615#endif /* LINUX */
616
617#ifdef SUNOS4
618	int pid = tcp->pid;
619#if 0
620	int n, m;
621	union {
622		long val;
623		char x[sizeof(long)];
624	} u;
625
626	if (addr & (sizeof(long) - 1)) {
627		/* addr not a multiple of sizeof(long) */
628		n = addr - (addr & -sizeof(long)); /* residue */
629		addr &= -sizeof(long); /* residue */
630		errno = 0;
631		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
632		if (errno) {
633			perror("umoven");
634			return -1;
635		}
636		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
637		addr += sizeof(long), laddr += m, len -= m;
638	}
639	while (len) {
640		errno = 0;
641		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
642		if (errno) {
643			perror("umoven");
644			return -1;
645		}
646		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
647		addr += sizeof(long), laddr += m, len -= m;
648	}
649#else /* !oldway */
650	int n;
651
652	while (len) {
653		n = MIN(len, PAGSIZ);
654		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
655		if (ptrace(PTRACE_READDATA, pid,
656			   (char *) addr, len, laddr) < 0) {
657			perror("umoven: ptrace(PTRACE_READDATA, ...)");
658			abort();
659			return -1;
660		}
661		len -= n;
662		addr += n;
663		laddr += n;
664	}
665#endif /* !oldway */
666#endif /* SUNOS4 */
667
668#ifdef USE_PROCFS
669#ifdef HAVE_MP_PROCFS
670	int fd = tcp->pfd_as;
671#else
672	int fd = tcp->pfd;
673#endif
674	lseek(fd, addr, SEEK_SET);
675	if (read(fd, laddr, len) == -1)
676		return -1;
677#endif /* USE_PROCFS */
678
679	return 0;
680}
681
682/*
683 * like `umove' but make the additional effort of looking
684 * for a terminating zero byte.
685 */
686int
687umovestr(tcp, addr, len, laddr)
688struct tcb *tcp;
689long addr;
690int len;
691char *laddr;
692{
693#ifdef USE_PROCFS
694#ifdef HAVE_MP_PROCFS
695	int fd = tcp->pfd_as;
696#else
697	int fd = tcp->pfd;
698#endif
699	/* Some systems (e.g. FreeBSD) can be upset if we read off the
700	   end of valid memory,  avoid this by trying to read up
701	   to page boundaries.  But we don't know what a page is (and
702	   getpagesize(2) (if it exists) doesn't necessarily return
703	   hardware page size).  Assume all pages >= 1024 (a-historical
704	   I know) */
705
706	int page = 1024; 	/* How to find this? */
707	int move = page - (addr & (page - 1));
708	int left = len;
709
710	lseek(fd, addr, SEEK_SET);
711
712	while (left) {
713		if (move > left) move = left;
714		if ((move = read(fd, laddr, move)) == -1)
715			return left != len ? 0 : -1;
716		if (memchr (laddr, 0, move)) break;
717		left -= move;
718		laddr += move;
719		addr += move;
720		move = page;
721	}
722#else /* !USE_PROCFS */
723	int started = 0;
724	int pid = tcp->pid;
725	int i, n, m;
726	union {
727		long val;
728		char x[sizeof(long)];
729	} u;
730
731	if (addr & (sizeof(long) - 1)) {
732		/* addr not a multiple of sizeof(long) */
733		n = addr - (addr & -sizeof(long)); /* residue */
734		addr &= -sizeof(long); /* residue */
735		errno = 0;
736		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
737		if (errno) {
738			if (started && (errno==EPERM || errno==EIO)) {
739				/* Ran into 'end of memory' - stupid "printpath" */
740				return 0;
741			}
742			perror("umovestr");
743			return -1;
744		}
745		started = 1;
746		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
747		while (n & (sizeof(long) - 1))
748			if (u.x[n++] == '\0')
749				return 0;
750		addr += sizeof(long), laddr += m, len -= m;
751	}
752	while (len) {
753		errno = 0;
754		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
755		if (errno) {
756			if (started && (errno==EPERM || errno==EIO)) {
757				/* Ran into 'end of memory' - stupid "printpath" */
758				return 0;
759			}
760			perror("umovestr");
761			return -1;
762		}
763		started = 1;
764		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
765		for (i = 0; i < sizeof(long); i++)
766			if (u.x[i] == '\0')
767				return 0;
768
769		addr += sizeof(long), laddr += m, len -= m;
770	}
771#endif /* !USE_PROCFS */
772	return 0;
773}
774
775#ifdef LINUX
776#ifndef SPARC
777#define PTRACE_WRITETEXT	101
778#define PTRACE_WRITEDATA	102
779#endif /* !SPARC */
780#endif /* LINUX */
781
782#ifdef SUNOS4
783
784static int
785uload(cmd, pid, addr, len, laddr)
786int cmd;
787int pid;
788long addr;
789int len;
790char *laddr;
791{
792#if 0
793	int n;
794
795	while (len) {
796		n = MIN(len, PAGSIZ);
797		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
798		if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
799			perror("uload: ptrace(PTRACE_WRITE, ...)");
800			return -1;
801		}
802		len -= n;
803		addr += n;
804		laddr += n;
805	}
806#else
807	int peek, poke;
808	int n, m;
809	union {
810		long val;
811		char x[sizeof(long)];
812	} u;
813
814	if (cmd == PTRACE_WRITETEXT) {
815		peek = PTRACE_PEEKTEXT;
816		poke = PTRACE_POKETEXT;
817	}
818	else {
819		peek = PTRACE_PEEKDATA;
820		poke = PTRACE_POKEDATA;
821	}
822	if (addr & (sizeof(long) - 1)) {
823		/* addr not a multiple of sizeof(long) */
824		n = addr - (addr & -sizeof(long)); /* residue */
825		addr &= -sizeof(long);
826		errno = 0;
827		u.val = ptrace(peek, pid, (char *) addr, 0);
828		if (errno) {
829			perror("uload: POKE");
830			return -1;
831		}
832		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
833		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
834			perror("uload: POKE");
835			return -1;
836		}
837		addr += sizeof(long), laddr += m, len -= m;
838	}
839	while (len) {
840		if (len < sizeof(long))
841			u.val = ptrace(peek, pid, (char *) addr, 0);
842		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
843		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
844			perror("uload: POKE");
845			return -1;
846		}
847		addr += sizeof(long), laddr += m, len -= m;
848	}
849#endif
850	return 0;
851}
852
853int
854tload(pid, addr, len, laddr)
855int pid;
856int addr, len;
857char *laddr;
858{
859	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
860}
861
862int
863dload(pid, addr, len, laddr)
864int pid;
865int addr;
866int len;
867char *laddr;
868{
869	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
870}
871
872#endif /* SUNOS4 */
873
874#ifndef USE_PROCFS
875
876int
877upeek(pid, off, res)
878int pid;
879long off;
880long *res;
881{
882	long val;
883
884#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
885	{
886		static int is_sun4m = -1;
887		struct utsname name;
888
889		/* Round up the usual suspects. */
890		if (is_sun4m == -1) {
891			if (uname(&name) < 0) {
892				perror("upeek: uname?");
893				exit(1);
894			}
895			is_sun4m = strcmp(name.machine, "sun4m") == 0;
896			if (is_sun4m) {
897				extern struct xlat struct_user_offsets[];
898				struct xlat *x;
899
900				for (x = struct_user_offsets; x->str; x++)
901					x->val += 1024;
902			}
903		}
904		if (is_sun4m)
905			off += 1024;
906	}
907#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
908	errno = 0;
909	val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
910	if (val == -1 && errno) {
911		perror("upeek: ptrace(PTRACE_PEEKUSER, ... )");
912		return -1;
913	}
914	*res = val;
915	return 0;
916}
917
918#endif /* !USE_PROCFS */
919
920long
921getpc(tcp)
922struct tcb *tcp;
923{
924
925#ifdef LINUX
926	long pc;
927#if defined(I386)
928	if (upeek(tcp->pid, 4*EIP, &pc) < 0)
929		return -1;
930#elif defined(IA64)
931	if (upeek(tcp->pid, PT_B0, &pc) < 0)
932		return -1;
933#elif defined(ARM)
934	if (upeek(tcp->pid, 4*15, &pc) < 0)
935		return -1;
936#elif defined(POWERPC)
937	if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
938		return -1;
939#elif defined(M68k)
940	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
941		return -1;
942#elif defined(ALPHA)
943	if (upeek(tcp->pid, REG_PC, &pc) < 0)
944		return -1;
945#elif defined(MIPS)
946 	if (upeek(tcp->pid, REG_EPC, &pc) < 0)
947 		return -1;
948#elif defined(SPARC)
949	struct regs regs;
950	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
951		return -1;
952	pc = regs.r_pc;
953#elif defined(S390)
954	if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
955#elif defined(HPPA)
956	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
957		return -1;
958#endif
959	return pc;
960#endif /* LINUX */
961
962#ifdef SUNOS4
963	/*
964	 * Return current program counter for `pid'
965	 * Assumes PC is never 0xffffffff
966	 */
967	struct regs regs;
968
969	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
970		perror("getpc: ptrace(PTRACE_GETREGS, ...)");
971		return -1;
972	}
973	return regs.r_pc;
974#endif /* SUNOS4 */
975
976#ifdef SVR4
977	/* XXX */
978	return 0;
979#endif /* SVR4 */
980
981#ifdef FREEBSD
982	struct reg regs;
983	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
984	return regs.r_eip;
985#endif /* FREEBSD */
986}
987
988void
989printcall(tcp)
990struct tcb *tcp;
991{
992
993#ifdef LINUX
994#ifdef I386
995	long eip;
996
997	if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
998		tprintf("[????????] ");
999		return;
1000	}
1001	tprintf("[%08lx] ", eip);
1002#elif defined(IA62)
1003	long ip;
1004
1005	if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1006		tprintf("[????????] ");
1007		return;
1008	}
1009	tprintf("[%08lx] ", ip);
1010#elif defined(POWERPC)
1011	long pc;
1012
1013	if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) {
1014		tprintf ("[????????] ");
1015		return;
1016	}
1017	tprintf("[%08lx] ", pc);
1018#elif defined(M68k)
1019	long pc;
1020
1021	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1022		tprintf ("[????????] ");
1023		return;
1024	}
1025	tprintf("[%08lx] ", pc);
1026#elif defined(ALPHA)
1027	long pc;
1028
1029	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1030		tprintf ("[????????] ");
1031		return;
1032	}
1033	tprintf("[%08lx] ", pc);
1034#elif defined(SPARC)
1035	struct regs regs;
1036	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1037		tprintf("[????????] ");
1038		return;
1039	}
1040	tprintf("[%08lx] ", regs.r_pc);
1041#elif defined(HPPA)
1042	long pc;
1043
1044	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1045		tprintf ("[????????] ");
1046		return;
1047	}
1048	tprintf("[%08lx] ", pc);
1049#elif defined(MIPS)
1050	long pc;
1051
1052	if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1053		tprintf ("[????????] ");
1054		return;
1055	}
1056	tprintf("[%08lx] ", pc);
1057#endif /* !architecture */
1058#endif /* LINUX */
1059
1060#ifdef SUNOS4
1061	struct regs regs;
1062
1063	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1064		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1065		tprintf("[????????] ");
1066		return;
1067	}
1068	tprintf("[%08x] ", regs.r_o7);
1069#endif /* SUNOS4 */
1070
1071#ifdef SVR4
1072	/* XXX */
1073	tprintf("[????????] ");
1074#endif
1075
1076#ifdef FREEBSD
1077	struct reg regs;
1078	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1079	tprintf("[%08x] ", regs.r_eip);
1080#endif /* FREEBSD */
1081}
1082
1083#ifndef USE_PROCFS
1084
1085int
1086setbpt(tcp)
1087struct tcb *tcp;
1088{
1089
1090#ifdef LINUX
1091#ifdef SPARC
1092	/* We simply use the SunOS breakpoint code. */
1093
1094	struct regs regs;
1095#define LOOPA	0x30800000	/* ba,a	0 */
1096
1097	if (tcp->flags & TCB_BPTSET) {
1098		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1099		return -1;
1100	}
1101	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1102		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1103		return -1;
1104	}
1105	tcp->baddr = regs.r_o7 + 8;
1106	errno = 0;
1107	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1108	if(errno) {
1109		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1110		return -1;
1111	}
1112
1113	/*
1114	 * XXX - BRUTAL MODE ON
1115	 * We cannot set a real BPT in the child, since it will not be
1116	 * traced at the moment it will reach the trap and would probably
1117	 * die with a core dump.
1118	 * Thus, we are force our way in by taking out two instructions
1119	 * and insert an eternal loop instead, in expectance of the SIGSTOP
1120	 * generated by out PTRACE_ATTACH.
1121	 * Of cause, if we evaporate ourselves in the middle of all this...
1122	 */
1123	errno = 0;
1124	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1125	if(errno) {
1126		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1127		return -1;
1128	}
1129	tcp->flags |= TCB_BPTSET;
1130
1131#else /* !SPARC */
1132#ifdef IA64
1133	/*
1134	 * Our strategy here is to replace the bundle that contained
1135	 * the clone() syscall with a bundle of the form:
1136	 *
1137	 *	{ 1: br 1b; br 1b; br 1b }
1138	 *
1139	 * This ensures that the newly forked child will loop
1140	 * endlessly until we've got a chance to attach to it.
1141	 */
1142	{
1143#		define LOOP0	0x0000100000000017
1144#		define LOOP1	0x4000000000200000
1145		unsigned long addr, ipsr;
1146		pid_t pid;
1147
1148		pid = tcp->pid;
1149		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1150			return -1;
1151		if (upeek(pid, PT_CR_IIP, &addr) < 0)
1152			return -1;
1153		tcp->baddr = addr | ((ipsr >> 41) & 0x3);	/* store "ri" in low two bits */
1154
1155		errno = 0;
1156		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0);
1157		tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0);
1158		if (errno) {
1159			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1160			return -1;
1161		}
1162
1163		errno = 0;
1164		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1165		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1166		if (errno) {
1167			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1168			return -1;
1169		}
1170		tcp->flags |= TCB_BPTSET;
1171	}
1172#else /* !IA64 */
1173
1174#if defined (I386)
1175#define LOOP	0x0000feeb
1176#elif defined (M68K)
1177#define LOOP	0x60fe0000
1178#elif defined (ALPHA)
1179#define LOOP	0xc3ffffff
1180#elif defined (POWERPC)
1181#define LOOP	0x0000feeb
1182#elif defined(ARM)
1183#define LOOP	0xEAFFFFFE
1184#elif defined(MIPS)
1185#define LOOP	0x1000ffff
1186#elif defined(S390)
1187#define LOOP	0xa7f40000	/* BRC 15,0 */
1188#elif defined(HPPA)
1189#define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */
1190#else
1191#error unknown architecture
1192#endif
1193
1194	if (tcp->flags & TCB_BPTSET) {
1195		fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1196		return -1;
1197	}
1198#if defined (I386)
1199	if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1200		return -1;
1201#elif defined (M68K)
1202	if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1203	  return -1;
1204#elif defined (ALPHA)
1205	return -1;
1206#elif defined (ARM)
1207	return -1;
1208#elif defined (MIPS)
1209	return -1;		/* FIXME: I do not know what i do - Flo */
1210#elif defined (POWERPC)
1211	if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)
1212		return -1;
1213#elif defined(S390)
1214	if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1215		return -1;
1216#elif defined(HPPA)
1217	if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1218		return -1;
1219	tcp->baddr &= ~0x03;
1220#else
1221#error unknown architecture
1222#endif
1223	if (debug)
1224		fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1225	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1226	if (errno) {
1227		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1228		return -1;
1229	}
1230	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1231	if (errno) {
1232		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1233		return -1;
1234	}
1235	tcp->flags |= TCB_BPTSET;
1236
1237#endif /* !IA64 */
1238#endif /* SPARC */
1239#endif /* LINUX */
1240
1241#ifdef SUNOS4
1242#ifdef SPARC	/* This code is slightly sparc specific */
1243
1244	struct regs regs;
1245#define BPT	0x91d02001	/* ta	1 */
1246#define LOOP	0x10800000	/* ba	0 */
1247#define LOOPA	0x30800000	/* ba,a	0 */
1248#define NOP	0x01000000
1249#if LOOPA
1250	static int loopdeloop[1] = {LOOPA};
1251#else
1252	static int loopdeloop[2] = {LOOP, NOP};
1253#endif
1254
1255	if (tcp->flags & TCB_BPTSET) {
1256		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1257		return -1;
1258	}
1259	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1260		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1261		return -1;
1262	}
1263	tcp->baddr = regs.r_o7 + 8;
1264	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1265				sizeof tcp->inst, (char *)tcp->inst) < 0) {
1266		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1267		return -1;
1268	}
1269
1270	/*
1271	 * XXX - BRUTAL MODE ON
1272	 * We cannot set a real BPT in the child, since it will not be
1273	 * traced at the moment it will reach the trap and would probably
1274	 * die with a core dump.
1275	 * Thus, we are force our way in by taking out two instructions
1276	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1277	 * generated by out PTRACE_ATTACH.
1278	 * Of cause, if we evaporate ourselves in the middle of all this...
1279	 */
1280	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1281			sizeof loopdeloop, (char *) loopdeloop) < 0) {
1282		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1283		return -1;
1284	}
1285	tcp->flags |= TCB_BPTSET;
1286
1287#endif /* SPARC */
1288#endif /* SUNOS4 */
1289
1290	return 0;
1291}
1292
1293int
1294clearbpt(tcp)
1295struct tcb *tcp;
1296{
1297
1298#ifdef LINUX
1299#if defined(I386)
1300	long eip;
1301#elif defined(POWERPC)
1302	long pc;
1303#elif defined(M68K)
1304	long pc;
1305#elif defined(ALPHA)
1306	long pc;
1307#elif defined(HPPA)
1308	long iaoq;
1309#endif /* architecture */
1310
1311#ifdef SPARC
1312	/* Again, we borrow the SunOS breakpoint code. */
1313	if (!(tcp->flags & TCB_BPTSET)) {
1314		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1315		return -1;
1316	}
1317	errno = 0;
1318	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1319	if(errno) {
1320		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1321		return -1;
1322	}
1323	tcp->flags &= ~TCB_BPTSET;
1324#elif defined(IA64)
1325	{
1326		unsigned long addr, ipsr;
1327		pid_t pid;
1328
1329		pid = tcp->pid;
1330
1331		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1332			return -1;
1333		if (upeek(pid, PT_CR_IIP, &addr) < 0)
1334			return -1;
1335
1336		/* restore original bundle: */
1337		errno = 0;
1338		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1339		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1340		if (errno) {
1341			perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1342			return -1;
1343		}
1344
1345		/* restore original "ri" in ipsr: */
1346		ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1347		errno = 0;
1348		ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1349		if (errno) {
1350			perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1351			return -1;
1352		}
1353
1354		tcp->flags &= ~TCB_BPTSET;
1355
1356		if (addr != (tcp->baddr & ~0x3)) {
1357			/* the breakpoint has not been reached yet.  */
1358			if (debug)
1359				fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1360					addr, tcp->baddr);
1361			return 0;
1362		}
1363	}
1364#else /* !IA64  && ! SPARC */
1365
1366	if (debug)
1367		fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1368	if (!(tcp->flags & TCB_BPTSET)) {
1369		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1370		return -1;
1371	}
1372	errno = 0;
1373	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1374	if (errno) {
1375		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1376		return -1;
1377	}
1378	tcp->flags &= ~TCB_BPTSET;
1379
1380#ifdef I386
1381	if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1382		return -1;
1383	if (eip != tcp->baddr) {
1384		/* The breakpoint has not been reached yet.  */
1385		if (debug)
1386			fprintf(stderr,
1387				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1388					eip, tcp->baddr);
1389		return 0;
1390	}
1391#elif defined(POWERPC)
1392	if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
1393		return -1;
1394	if (pc != tcp->baddr) {
1395		/* The breakpoint has not been reached yet.  */
1396		if (debug)
1397			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1398				pc, tcp->baddr);
1399		return 0;
1400	}
1401#elif defined(M68K)
1402	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1403		return -1;
1404	if (pc != tcp->baddr) {
1405		/* The breakpoint has not been reached yet.  */
1406		if (debug)
1407			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1408				pc, tcp->baddr);
1409		return 0;
1410	}
1411#elif defined(ALPHA)
1412	if (upeek(tcp->pid, REG_PC, &pc) < 0)
1413		return -1;
1414	if (pc != tcp->baddr) {
1415		/* The breakpoint has not been reached yet.  */
1416		if (debug)
1417			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1418				pc, tcp->baddr);
1419		return 0;
1420	}
1421#elif defined(HPPA)
1422	if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1423		return -1;
1424	iaoq &= ~0x03;
1425	if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1426		/* The breakpoint has not been reached yet.  */
1427		if (debug)
1428			fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1429				iaoq, tcp->baddr);
1430		return 0;
1431	}
1432	iaoq = tcp->baddr | 3;
1433	/* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1434	 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1435	 * has no significant effect.
1436	 */
1437	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1438	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1439#endif /* arch */
1440#endif /* !SPARC && !IA64 */
1441#endif /* LINUX */
1442
1443#ifdef SUNOS4
1444#ifdef SPARC
1445
1446#if !LOOPA
1447	struct regs regs;
1448#endif
1449
1450	if (!(tcp->flags & TCB_BPTSET)) {
1451		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1452		return -1;
1453	}
1454	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1455				sizeof tcp->inst, (char *) tcp->inst) < 0) {
1456		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1457		return -1;
1458	}
1459	tcp->flags &= ~TCB_BPTSET;
1460
1461#if !LOOPA
1462	/*
1463	 * Since we don't have a single instruction breakpoint, we may have
1464	 * to adjust the program counter after removing the our `breakpoint'.
1465	 */
1466	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1467		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1468		return -1;
1469	}
1470	if ((regs.r_pc < tcp->baddr) ||
1471				(regs.r_pc > tcp->baddr + 4)) {
1472		/* The breakpoint has not been reached yet */
1473		if (debug)
1474			fprintf(stderr,
1475				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1476					regs.r_pc, tcp->parent->baddr);
1477		return 0;
1478	}
1479	if (regs.r_pc != tcp->baddr)
1480		if (debug)
1481			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1482				regs.r_pc, tcp->baddr);
1483
1484	regs.r_pc = tcp->baddr;
1485	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1486		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1487		return -1;
1488	}
1489#endif /* LOOPA */
1490#endif /* SPARC */
1491#endif /* SUNOS4 */
1492
1493	return 0;
1494}
1495
1496#endif /* !USE_PROCFS */
1497
1498#ifdef SUNOS4
1499
1500static int
1501getex(pid, hdr)
1502int pid;
1503struct exec *hdr;
1504{
1505	int n;
1506
1507	for (n = 0; n < sizeof *hdr; n += 4) {
1508		long res;
1509		if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1510			return -1;
1511		memcpy(((char *) hdr) + n, &res, 4);
1512	}
1513	if (debug) {
1514		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1515			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1516		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1517			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1518	}
1519	return 0;
1520}
1521
1522int
1523fixvfork(tcp)
1524struct tcb *tcp;
1525{
1526	int pid = tcp->pid;
1527	/*
1528	 * Change `vfork' in a freshly exec'ed dynamically linked
1529	 * executable's (internal) symbol table to plain old `fork'
1530	 */
1531
1532	struct exec hdr;
1533	struct link_dynamic dyn;
1534	struct link_dynamic_2 ld;
1535	char *strtab, *cp;
1536
1537	if (getex(pid, &hdr) < 0)
1538		return -1;
1539	if (!hdr.a_dynamic)
1540		return -1;
1541
1542	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1543		fprintf(stderr, "Cannot read DYNAMIC\n");
1544		return -1;
1545	}
1546	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1547		fprintf(stderr, "Cannot read link_dynamic_2\n");
1548		return -1;
1549	}
1550	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1551		fprintf(stderr, "fixvfork: out of memory\n");
1552		return -1;
1553	}
1554	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1555					(int)ld.ld_symb_size, strtab) < 0)
1556		goto err;
1557
1558#if 0
1559	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1560		fprintf(stderr, "[symbol: %s]\n", cp);
1561		cp += strlen(cp)+1;
1562	}
1563	return 0;
1564#endif
1565	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1566		if (strcmp(cp, "_vfork") == 0) {
1567			if (debug)
1568				fprintf(stderr, "fixvfork: FOUND _vfork\n");
1569			strcpy(cp, "_fork");
1570			break;
1571		}
1572		cp += strlen(cp)+1;
1573	}
1574	if (cp < strtab + ld.ld_symb_size)
1575		/*
1576		 * Write entire symbol table back to avoid
1577		 * memory alignment bugs in ptrace
1578		 */
1579		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1580					(int)ld.ld_symb_size, strtab) < 0)
1581			goto err;
1582
1583	free(strtab);
1584	return 0;
1585
1586err:
1587	free(strtab);
1588	return -1;
1589}
1590
1591#endif /* SUNOS4 */
1592