util.c revision 87ea1f4fe68c6110a96a76f8601b3e204200082d
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
64dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
74dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman *                     Linux for s390 port by D.J. Barrow
84dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#include <signal.h>
39d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#include <sys/syscall.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/user.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
431d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
441d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#include <sys/uio.h>
451d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
4776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <machine/reg.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <a.out.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <link.h>
5076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
5136915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman
5243a7482edbc7142b91e95d7aedeb9d121fc4880fWichert Akkerman#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
5376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <linux/ptrace.h>
541e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath#endif
5536915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman
568b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#if defined(LINUX) && defined(IA64)
57d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# include <asm/ptrace_offsets.h>
58d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# include <asm/rse.h>
598b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
608b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
6136915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman#ifdef HAVE_SYS_REG_H
6236915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman#include <sys/reg.h>
6336915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman# define PTRACE_PEEKUSR PTRACE_PEEKUSER
64faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(HAVE_LINUX_PTRACE_H)
65faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#undef PTRACE_SYSCALL
66ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_IA64_FPREG
67ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define ia64_fpreg XXX_ia64_fpreg
68ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
69ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define pt_all_user_regs XXX_pt_all_user_regs
71ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
72faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#include <linux/ptrace.h>
73ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef ia64_fpreg
74ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef pt_all_user_regs
752e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman#endif
762e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman
7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/utsname.h>
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
816d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined(LINUXSPARC)
829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
834db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# define fpq kernel_fpq
844db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# define fq kernel_fq
854db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# define fpu kernel_fpu
864db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# include <asm/reg.h>
874db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# undef fpq
884db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# undef fq
894db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath# undef fpu
909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
916d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC64)
926d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# define r_pc r_tpc
936d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# undef PTRACE_GETREGS
946d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# define PTRACE_GETREGS PTRACE_GETREGS64
956d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# undef PTRACE_SETREGS
966d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# define PTRACE_SETREGS PTRACE_SETREGS64
976d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* SPARC64 */
986d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath
999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#if !defined(__GLIBC__)
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <linux/unistd.h>
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman          type5,arg5,syscall) \
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantype name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ \
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman      long __res; \
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman\
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %2, %%o1\n\t" \
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %3, %%o2\n\t" \
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %4, %%o3\n\t" \
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %5, %%o4\n\t" \
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %6, %%g1\n\t" \
1156d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC64)
1166d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath                  "t 0x6d\n\t" \
1176d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "t 0x10\n\t" \
1196d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "bcc 1f\n\t" \
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "or %%g0, %%o0, %0\n\t" \
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "sub %%g0, %%o0, %0\n\t" \
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  "1:\n\t" \
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  : "=r" (__res) \
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  : "0" ((long)(arg1)),"1" ((long)(arg2)), \
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                    "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                    "i" (__NR_##syscall)  \
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman                  : "g1", "o0", "o1", "o2", "o3", "o4"); \
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanif (__res>=0) \
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman        return (type) __res; \
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerrno = -__res; \
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreturn -1; \
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define _ptrace
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* macros */
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MAX
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define MAX(a,b)		(((a) > (b)) ? (a) : (b))
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MIN
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define MIN(a,b)		(((a) < (b)) ? (a) : (b))
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
151a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#if 0
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_tv(tv, a, b)
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint a;
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint b;
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a;
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = b;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
161a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#endif
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_nz(a)
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *a;
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return a->tv_sec || a->tv_usec;
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_cmp(a, b)
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *a, *b;
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec < b->tv_sec
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec > b->tv_sec
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandouble
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_float(tv)
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv;
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return tv->tv_sec + tv->tv_usec/1000000.0;
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_add(tv, a, b)
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a, *b;
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec + b->tv_sec;
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec + b->tv_usec;
19658372f52ac5f824be687c01bfc1db1ffb963f91eRoland McGrath	if (tv->tv_usec >= 1000000) {
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec++;
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec -= 1000000;
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_sub(tv, a, b)
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a, *b;
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec - b->tv_sec;
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec - b->tv_usec;
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (((long) tv->tv_usec) < 0) {
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec--;
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec += 1000000;
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_div(tv, a, n)
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a;
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint n;
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_mul(tv, a, n)
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a;
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint n;
22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec * n;
230fefdd97156bb2f86c5b6596dc7e28d954516b3edDmitry V. Levin	tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinconst char *
235ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinxlookup(const struct xlat *xlat, int val)
23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (; xlat->str != NULL; xlat++)
23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val == val)
23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return xlat->str;
24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
24676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
247ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
249ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
25076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
25276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", str);
25376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
25476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
25576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
25676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanaddflags(xlat, flags)
264d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n++;
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
283a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
284a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Interpret `xlat' as an array of flags/
285a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
286a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
287a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
288a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
289a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
290a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
291a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
292a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
293a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
294a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	strcpy(outstr, prefix);
295a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
296a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
297a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
298a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
299a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath				strcat(outstr, "|");
300a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, xlat->str);
301a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			flags &= ~xlat->val;
302a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
303a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
304a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
305a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
306a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
307a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, "|");
308a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		sprintf(outstr + strlen(outstr), "%#x", flags);
309a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
310a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
311a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
312a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
313a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
315b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathprintflags(xlat, flags, dflt)
316d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
318b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathconst char *dflt;
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *sep;
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
337b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
338b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
339b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
340b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
341b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
342b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
343b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
344b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
345b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
346b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
347b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
348b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
349b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
350b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
351b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
35276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
353b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
35476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
35576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
35676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
35876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintnum(tcp, addr, fmt)
35976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
36076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
36176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
36276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
363eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
36876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
37376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3786bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
3799814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathprintnum_int(tcp, addr, fmt)
3809814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathstruct tcb *tcp;
3819814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathlong addr;
3829814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathchar *fmt;
3839814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3849814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3859814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3869814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
3879814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
3889814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3899814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3909814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
3919814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
3929814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3939814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3949814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
3959814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
3969814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
3979814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
3989814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3999814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4006bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathprintuid(text, uid)
4016bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathconst char *text;
4026bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathunsigned long uid;
4036bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4046bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
4056bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
4066bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4076bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
40876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
4106d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrathstatic int
411bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinstring_quote(const char *instr, char *outstr, int len, int size)
41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
413bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
414bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
415bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	int usehex = 0, c, i;
41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
417bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
418bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
419bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
420bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
421bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
4226d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath			if (len < 0 && i == size - 2 && c != '\0')
4236d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath				++i;
424bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (len < 0 && c == '\0')
425bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
426bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
427bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
428bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
429bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
430bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
432bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
433bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
434bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
435bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
436bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
437bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
438bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (len < 0 && c == '\0')
439bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
440bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			sprintf(s, "\\x%02x", c);
441bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			s += 4;
442bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
443bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
444bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
445bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
4466d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath			if (len < 0 && i == size - 2 && c != '\0')
4476d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath				++i;
448bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (len < 0 && c == '\0')
449bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
450bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
451bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
452bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
453bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
454bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
455bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
456bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
457bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
458bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
459bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
460bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
461bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
462bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
463bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
464bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
465bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
466bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
467bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
468bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
469bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
470bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
471bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
472bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
473bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
475bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
476bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
477bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
478bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					else if (i + 1 < size
479bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						 && isdigit(ustr[i + 1])) {
480bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%03o", c);
481bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += 4;
482bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					} else {
483bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%o", c);
484bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += strlen(s);
485bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
486bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
487bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
48876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
49076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
491bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
492bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
4936d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
4946d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	/* Return nonzero if the string was unterminated.  */
4956d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	return i == size;
49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (n > sizeof path - 1)
502b15c4e47ff5b2b0dd71fa10472eafb1d5abf4c5fRoland McGrath		n = sizeof path - 1;
503b15c4e47ff5b2b0dd71fa10472eafb1d5abf4c5fRoland McGrath
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (addr == 0) {
505371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
509bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	path[n] = '\0';
510bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (umovestr(tcp, addr, n + 1, path) < 0)
51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
513bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		int trunc = (path[n] != '\0');
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (trunc)
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			path[n] = '\0';
5186d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath		if (string_quote(path, outstr, -1, n + 1) || trunc)
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			strcat(outstr, "...");
520bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		tprintf("%s", outstr);
52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
525bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
526bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
527bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	printpathn(tcp, addr, sizeof path - 1);
528bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
529bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
530bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
531bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintstr(struct tcb *tcp, long addr, int len)
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
533bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
5356d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!str) {
542a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath		if ((str = malloc(max_strlen + 1)) == NULL
543779c466c0fdb4a0e4039d5ed407d1e6f61c23437Roland McGrath		    || (outstr = malloc(4*max_strlen
544779c466c0fdb4a0e4039d5ed407d1e6f61c23437Roland McGrath					+ sizeof "\"\"...")) == NULL) {
54546100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
550bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
552bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
553bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
559bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = MIN(len, max_strlen + 1);
560bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
56276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
5666d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	if (string_quote(str, outstr, len, size))
567bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		strcat(outstr, "...");
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
5721d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
5731d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
5741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesdumpiov(tcp, len, addr)
5751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesstruct tcb * tcp;
5761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesint len;
5771d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hugheslong addr;
5781d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
5794ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
5804ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
5814ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
5824ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
5834ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
5844ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
5854ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
5864ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5874ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
5884ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
5894ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5904ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
5914ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
5924ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5934ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
5944ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
5951d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
5964ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
5974ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
5984ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
5994ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6001d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
601aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
6021d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
6034ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
6044ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
6054ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
606aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
6071d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
6081d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
609aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
6101d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
6111d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        /* include the buffer number to make it easy to
6121d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                         * match up the trace with the source */
6131d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        tprintf(" * %lu bytes in buffer %d\n",
6144ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                (unsigned long)iov_iov_len(i), i);
6154ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                        dumpstr(tcp, (long) iov_iov_base(i),
6164ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                iov_iov_len(i));
6171d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                }
6181d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
6191d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
6204ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6214ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6224ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6234ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6241d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6251d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6261d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandumpstr(tcp, addr, len)
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
64346100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumoven(tcp, addr, len, laddr)
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
7005daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
7135daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
7175daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			/* But if not started, we had a bogus address. */
7181c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
7191c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("ptrace: umoven");
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
7225daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
7305daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
7341c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
7354db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath				perror("ptrace: umoven");
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
7385daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !oldway */
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_READDATA, pid,
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			   (char *) addr, len, laddr) < 0) {
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven: ptrace(PTRACE_READDATA, ...)");
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			abort();
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !oldway */
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
796ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
797aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
7989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
799aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
801aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
802aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
804bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumovestr(tcp, addr, len, laddr)
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
820bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
821aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
822aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
823aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
824aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
825aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
826aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
827aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
828aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
829aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
830aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
831aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
832aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
833aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int page = 1024; 	/* How to find this? */
834aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
835aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
836aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
837aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
838aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
839aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
840aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
8419cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
842aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
843aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (memchr (laddr, 0, move)) break;
844aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
845aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
846aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
847aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
848aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
849bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
8505daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8655daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8691c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8701c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8735daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8845daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8881c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8891c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8925daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
901aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
9056d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if !defined (SPARC) && !defined(SPARC64)
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITETEXT	101
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITEDATA	102
9086d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 */
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuload(cmd, pid, addr, len, laddr)
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint cmd;
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: ptrace(PTRACE_WRITE, ...)");
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(peek, pid, (char *) addr, 0);
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			u.val = ptrace(peek, pid, (char *) addr, 0);
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantload(pid, addr, len, laddr)
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr, len;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandload(pid, addr, len, laddr)
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanupeek(pid, off, res)
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong off;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong *res;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1026d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				extern const struct xlat struct_user_offsets[];
1027d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (val == -1 && errno) {
10401e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath		char buf[60];
10410e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
10421e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath		perror(buf);
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1051a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#if 0
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangetpc(tcp)
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1059f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#if defined(I386)
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &pc) < 0)
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
10620e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
10630e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &pc) < 0)
10640e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
10658b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#elif defined(IA64)
10668b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	if (upeek(tcp->pid, PT_B0, &pc) < 0)
10678b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return -1;
1068f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ARM)
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*15, &pc) < 0)
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin#elif defined(BFIN)
107287ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	if (upeek(tcp->pid, REG_PC, &pc) < 0)
107387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return -1;
1074f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(POWERPC)
1075eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107784fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1080f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ALPHA)
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0)
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1083f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
1084f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman 	if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1085f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman 		return -1;
10866d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
10879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
10909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	pc = regs.r_pc;
109110a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
10924dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman	if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
109310a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig		return -1;
1094c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1095c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1096c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1097ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1098ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1099ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
1100f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1101e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath       if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1102e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath               return -1;
11037a0b649aeace5c1e1efe4a1d7b1ae6e3a87e0d44Wichert Akkerman#endif
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return pc;
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Return current program counter for `pid'
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Assumes PC is never 0xffffffff
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getpc: ptrace(PTRACE_GETREGS, ...)");
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return regs.r_pc;
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1126bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1127bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1129bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	return regs.r_eip;
1130bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
1132a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#endif
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintcall(tcp)
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
11387a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
11397a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
11407a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
11477a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1151eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
1152eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif defined(S390) || defined(S390X)
1153eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         long psw;
1154eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
11557a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath                 PRINTBADPC;
1156eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath                 return;
1157eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         }
1158eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#ifdef S390
1159eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         tprintf("[%08lx] ", psw);
1160eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif S390X
1161eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath       tprintf("[%16lx] ", psw);
1162eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#endif
1163eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
11640e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
11650e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
11660e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
11670e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
11687a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
11690e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
11700e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
11710e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
1172ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(IA64)
11738b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
11748b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
11758b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	if (upeek(tcp->pid, PT_B0, &ip) < 0) {
11767a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
11778b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
11788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
11798b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
1180faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1183eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
118884fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
1196faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
12007a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
12046d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
12059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
12077a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tprintf("[%08lx] ", regs.r_pc);
1211c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1212c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1213c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1214c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1215c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		tprintf ("[????????] ");
1216c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1217c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1218c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
121975c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman#elif defined(MIPS)
122075c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
122175c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
122275c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
122375c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		tprintf ("[????????] ");
122475c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
122575c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
122675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
1227ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1228ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1229ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1230ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1231ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               tprintf ("[????????] ");
1232ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return;
1233ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       }
1234ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       tprintf("[%08lx] ", pc);
1235f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1236e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1237e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1238e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
12397a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
1240e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1241e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1242e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
1243ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(ARM)
1244ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1245e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1246ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	if (upeek(tcp->pid, 4*15, &pc) < 0) {
12477a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1248ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1249ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1250ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
125187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin#elif defined(BFIN)
125287ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	long pc;
125387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin
125487ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	if (upeek(tcp->pid, PT_PC, &pc) < 0) {
125587ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		PRINTBADPC;
125687ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return;
125787ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	}
125887ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	tprintf("[%08lx] ", pc);
1259faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* !architecture */
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
12677a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
12757a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1278bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1280bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1281bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1285bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1287d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#if defined LINUX
1288d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12893291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath#include "syscall.h"
12903291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
1291d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#include <sys/syscall.h>
1292d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifndef CLONE_PTRACE
1293d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define CLONE_PTRACE    0x00002000
1294d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1295d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath#ifndef CLONE_VFORK
1296d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath# define CLONE_VFORK     0x00004000
1297d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath#endif
12988fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil#ifndef CLONE_VM
12998fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil# define CLONE_VM        0x00000100
13008fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil#endif
130176989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#ifndef CLONE_STOPPED
130276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath# define CLONE_STOPPED   0x02000000
130376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#endif
1304d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1305d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef IA64
1306d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
130708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
130808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
130908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_fork	2
131008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_vfork	190
131108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1312d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1313d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1314d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1315d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1316d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
13171f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
13181f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1319d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13201f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
13211f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
13221f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
132308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
13241f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
132508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
13261f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
1327d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1328d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1329d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1330d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1331d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1332d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
13331f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1334d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13351f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1336d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1337d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1338d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1339d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1340d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1341d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1342d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1343d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1344d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
134508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
134608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
134708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
134808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = upeek (tcp->pid, PT_R11, valp);
134908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
135008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
135108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
135208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
135308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1354d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1355d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1356d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1357d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1358d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
135908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
136008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
136108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
136208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = upeek (tcp->pid, PT_R9, valp);
136308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
136408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
136508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
136608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
136708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1368d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1369d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1370d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1371d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1372d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1373d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
137408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
137508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
137608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
137708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
137808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
137908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
138008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
138108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1382d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
138308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1384d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1385d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1386d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1387d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1388d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1389d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
139008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
139108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
139208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
139308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
139408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
139508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
139608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
139708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1398d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
139908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1400d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1401d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1402d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1403b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1404b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1405b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
1406b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath# define restore_arg0(tcp, state, val) ((void) (state), 0)
1407b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath# define restore_arg1(tcp, state, val) ((void) (state), 0)
1408b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
14096d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined (SPARC) || defined (SPARC64)
1410d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1411d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef struct regs arg_setup_state;
1412d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1413d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) \
1414d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1415d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state) \
1416d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1417d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1418d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1419d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1420d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1421d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1422e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) 0
1423d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1424d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1425d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1426d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# if defined S390 || defined S390X
14277b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
14287b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
14297b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
14307b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
14317b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg0_offset	PT_GPR3
14327b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg1_offset	PT_ORIGGPR2
14337b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
14347b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg1(tcp, state, val) ((void) (state), 0)
1435c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg0_index	1
1436c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg1_index	0
1437d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (ALPHA) || defined (MIPS)
1438d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	REG_A0
1439d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	(REG_A0+1)
1440d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (POWERPC)
1441eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg0_offset	(sizeof(unsigned long)*PT_R3)
1442eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg1_offset	(sizeof(unsigned long)*PT_R4)
14437b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
1444d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (HPPA)
1445d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	 PT_GR26
1446d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	 (PT_GR26-4)
14477f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath# elif defined (X86_64)
14487f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
14497f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
1450ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath# elif defined (SH)
1451ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg0_offset	(4*(REG_REG0+4))
1452ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg1_offset	(4*(REG_REG0+5))
1453f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath# elif defined (SH64)
1454e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath   /* ABI defines arg0 & 1 in r2 & r3 */
1455e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg0_offset   (REG_OFFSET+16)
1456e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg1_offset   (REG_OFFSET+24)
1457e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define restore_arg0(tcp, state, val) 0
1458d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# else
1459d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	0
1460d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	4
1461ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  if defined ARM
1462e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#   define restore_arg0(tcp, state, val) 0
1463e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#  endif
1464d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# endif
1465d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1466d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1467d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1468d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) (0)
1469d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1470d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, cookie, valp) \
1471d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (upeek ((tcp)->pid, arg0_offset, (valp)))
1472d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, cookie, valp) \
1473d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (upeek ((tcp)->pid, arg1_offset, (valp)))
1474d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1475d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1476d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, void *cookie, long val)
1477d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1478ca85b97c9cea63db45e59a345218b902936b693dRoland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1479d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1480d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1481d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1482d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, void *cookie, long val)
1483d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1484d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1485d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1486d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1487d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1488d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1489e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg0
1490e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1491e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1492e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg1
1493e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1494e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1495d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
149690d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#ifndef arg0_index
149790d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg0_index 0
149890d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg1_index 1
149990d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#endif
150090d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1501d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1502d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathsetbpt(tcp)
1503d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1504d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
15053291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1506d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	extern int change_syscall(struct tcb *, int);
1507d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1508d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1509d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1510d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1511d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1512d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1513d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
15143291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
15153291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
15163291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
15173291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
15183291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
15193291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
15203291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
15213291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
15223291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
15233291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
15243291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
15253291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
15263291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
15273291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
152876989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
15299383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#ifdef SYS_vfork
15309383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
15319383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#endif
1532d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1533d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
15349b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#endif
15359b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#if defined SYS_fork || defined SYS_vfork
1536d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		if (arg_setup (tcp, &state) < 0
1537d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1538d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
15393291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		    || change_syscall(tcp, clone_scno[current_personality]) < 0
1540d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1541d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg1 (tcp, &state, 0) < 0
1542d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || arg_finish_change (tcp, &state) < 0)
1543d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1544c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1545c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1546d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1547d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1548d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1549d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1550d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone:
1551d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_clone2
1552d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone2:
1553d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
15548fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
15558fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   contrary to x86 SYS_vfork above.  Even on x86 we turn the
15568fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
15578fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
15588fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
15598fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
15608fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
15618fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1562d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		if ((arg_setup (tcp, &state) < 0
1563d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || set_arg0 (tcp, &state,
1564d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath				 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
15658fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
15668fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				     ? CLONE_VFORK | CLONE_VM : 0)) < 0
1567d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || arg_finish_change (tcp, &state) < 0))
1568d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    return -1;
1569d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1570c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1571c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1572d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1573d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1574d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1575d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1576d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1577d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1578d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1579d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1580d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1581d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1582d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1583d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1584d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathclearbpt(tcp)
1585d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1586d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1587d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1588d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (arg_setup (tcp, &state) < 0
1589e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1590e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1591d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	    || arg_finish_change (tcp, &state))
1592d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1593d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1594d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1595d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1596d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1597d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1598d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermansetbpt(tcp)
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
16056d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* We simply use the SunOS breakpoint code. */
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
16096d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	unsigned long inst;
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop instead, in expectance of the SIGSTOP
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
16396d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst = LOOPA;
16406d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC64)
16416d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst <<= 32;
16426d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst |= (tcp->inst[0] & 0xffffffffUL);
16436d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif
16446d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16516d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !SPARC && !SPARC64 */
16528b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#ifdef IA64
16537b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
16547b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#		define LOOP	0x0000feeb
16557b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (tcp->flags & TCB_BPTSET) {
16567b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: bpt already set in pid %u\n",
16577b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid);
16587b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
16597b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
16607b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
16617b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
16627b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
16637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] setting bpt at %lx\n",
16647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid, tcp->baddr);
16657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
16667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      (char *) tcp->baddr, 0);
16677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
16687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
16697b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
16707b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
16717b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
16727b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
16737b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
16747b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
16757b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
16767b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags |= TCB_BPTSET;
16777b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
16787b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/*
16797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * Our strategy here is to replace the bundle that
16807b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * contained the clone() syscall with a bundle of the
16817b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * form:
16827b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
16837b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *	{ 1: br 1b; br 1b; br 1b }
16847b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
16857b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * This ensures that the newly forked child will loop
16867b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * endlessly until we've got a chance to attach to it.
16877b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 */
16888b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP0	0x0000100000000017
16898b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP1	0x4000000000200000
16908b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
16918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
16928b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
16938b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
16948b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
16958b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16968b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IIP, &addr) < 0)
16978b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/* store "ri" in low two bits */
16997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->baddr = addr | ((ipsr >> 41) & 0x3);
17008b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
17018b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
17027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
17037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
17047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
17057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
17068b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
17078b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
17088b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
17098b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
17108b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
17118b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
17128b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
17138b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
17148b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
17158b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
17168b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
17178b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
17188b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags |= TCB_BPTSET;
17198b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
17208b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#else /* !IA64 */
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17220e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined (I386) || defined(X86_64)
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x0000feeb
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x60fe0000
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
17274dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xc3ffffff
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
17291e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath#define LOOP	0x48000000
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined(ARM)
17319a8a37f2b28d1c0d3f57951fd5aeeb96ff7d2f16Wichert Akkerman#define LOOP	0xEAFFFFFE
1732f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
17334dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0x1000ffff
17344dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#elif defined(S390)
17354dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xa7f40000	/* BRC 15,0 */
173610a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390X)
173710a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1738c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1739c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */
1740ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1741ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#ifdef __LITTLE_ENDIAN__
1742ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0x0000affe
1743ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#else
1744ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0xfeaf0000
1745ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#endif
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined (I386)
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
17570e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined (X86_64)
17580e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
17590e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	  return -1;
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ARM)
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
1767f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined (MIPS)
1768f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman	return -1;		/* FIXME: I do not know what i do - Flo */
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
1770eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
177210a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
17734dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman	if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
17744dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman		return -1;
1775c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1776c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1777c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1778c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tcp->baddr &= ~0x03;
1779ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1780ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1781ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17998b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif /* !IA64 */
18006d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* SPARC || SPARC64 */
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC	/* This code is slightly sparc specific */
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1806e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define BPT	0x91d02001	/* ta	1 */
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x10800000	/* ba	0 */
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define NOP	0x01000000
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if LOOPA
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *)tcp->inst) < 0) {
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanclearbpt(tcp)
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
18610e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined(I386) || defined(X86_64)
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
1863faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1865faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1867faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1869c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1870c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long iaoq;
1871ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1872ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1873faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* architecture */
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18756d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Again, we borrow the SunOS breakpoint code. */
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
1888faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(IA64)
18897b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
18907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		unsigned long addr;
18917b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
18927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
18937b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
18947b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (!(tcp->flags & TCB_BPTSET)) {
18957b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
18967b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
18977b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
18987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		errno = 0;
18997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
19007b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
19017b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
19027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
19037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
19047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
19057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
19067b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
19077b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
19087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (addr != tcp->baddr) {
19097b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			/* The breakpoint has not been reached yet.  */
19107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			if (debug)
19117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				fprintf(stderr,
19127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
19137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman						addr, tcp->baddr);
19147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return 0;
19157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
19167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
19178b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
19188b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
19198b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19208b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
19218b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19228b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
19238b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
19248b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IIP, &addr) < 0)
19258b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
19268b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19278b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original bundle: */
19288b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
19298b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
19308b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
19318b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
19328b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
19338b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
19348b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
19358b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19368b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original "ri" in ipsr: */
19378b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
19388b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
19398b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
19408b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
19418b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
19428b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
19438b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
19448b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
19468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
19478b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (addr != (tcp->baddr & ~0x3)) {
19488b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			/* the breakpoint has not been reached yet.  */
19498b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			if (debug)
19508b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman				fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
19518b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman					addr, tcp->baddr);
19528b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return 0;
19538b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
19548b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
19556d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !IA64  && !SPARC && !SPARC64 */
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &eip) < 0)
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (eip != tcp->baddr) {
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					eip, tcp->baddr);
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
19820e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
19830e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &eip) < 0)
19840e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
19850e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (eip != tcp->baddr) {
19860e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		/* The breakpoint has not been reached yet.  */
19870e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		if (debug)
19880e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig			fprintf(stderr,
19890e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
19900e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig					eip, tcp->baddr);
19910e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return 0;
19920e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
1993c792698a99b640e7d256e8692c992bd967f0c5b2Wichert Akkerman#elif defined(POWERPC)
1994eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2003faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2013faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0)
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2023c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
2024c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
2025c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
2026c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq &= ~0x03;
2027c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2028c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		/* The breakpoint has not been reached yet.  */
2029c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		if (debug)
2030c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2031c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman				iaoq, tcp->baddr);
2032c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return 0;
2033c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
2034c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq = tcp->baddr | 3;
2035c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	/* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2036c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2037c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * has no significant effect.
2038c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 */
2039c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2040c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
2041ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
2042ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
2043ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
2044ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        if (pc != tcp->baddr) {
2045ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                /* The breakpoint has not been reached yet.  */
2046ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                if (debug)
2047ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                        fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2048ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                                pc, tcp->baddr);
2049ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                return 0;
2050ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        }
2051ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
2052faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* arch */
20536d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 && !IA64 */
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
2060e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * to adjust the program counter after removing the our `breakpoint'.
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((regs.r_pc < tcp->baddr) ||
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(regs.r_pc > tcp->baddr + 4)) {
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					regs.r_pc, tcp->parent->baddr);
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LOOPA */
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2109d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
2110d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
2111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangetex(pid, hdr)
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct exec *hdr;
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfixvfork(tcp)
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getex(pid, &hdr) < 0)
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
216646100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[symbol: %s]\n", cp);
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
2207