util.c revision 1c459769f69ff7cac0e12f934517e1ab349b9cc0
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
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
284b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathprintflags(xlat, flags, dflt)
285d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
287b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathconst char *dflt;
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *sep;
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
306b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
307b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
308b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
309b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
310b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
311b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
312b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
313b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
314b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
315b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
316b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
317b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
318b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
319b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
320b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
322b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintnum(tcp, addr, fmt)
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
332eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3476bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
3489814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathprintnum_int(tcp, addr, fmt)
3499814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathstruct tcb *tcp;
3509814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathlong addr;
3519814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathchar *fmt;
3529814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3539814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3549814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3559814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
3569814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
3579814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3589814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3599814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
3609814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
3619814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3629814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3639814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
3649814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
3659814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
3669814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
3679814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3689814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
3696bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathprintuid(text, uid)
3706bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathconst char *text;
3716bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathunsigned long uid;
3726bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
3736bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
3746bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
3756bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
3766bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
379a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrathstatic void
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstring_quote(str)
381a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrathconst char *str;
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char buf[2 * MAXPATHLEN + 1];
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!strpbrk(str, "\"\'\\")) {
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("\"%s\"", str);
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (s = buf; *str; str++) {
39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (*str) {
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case '\"': case '\'': case '\\':
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			*s++ = '\\'; *s++ = *str; break;
39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			*s++ = *str; break;
39676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*s = '\0';
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\"%s\"", buf);
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
40276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintpath(tcp, addr)
40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
407371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath	if (addr == 0)
408371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
409371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath	else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		string_quote(path);
41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
41476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintpathn(tcp, addr, n)
41876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint n;
42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
422b15c4e47ff5b2b0dd71fa10472eafb1d5abf4c5fRoland McGrath	if (n >= sizeof path)
423b15c4e47ff5b2b0dd71fa10472eafb1d5abf4c5fRoland McGrath		n = sizeof path - 1;
424b15c4e47ff5b2b0dd71fa10472eafb1d5abf4c5fRoland McGrath
425371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath	if (addr == 0)
426371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
427371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath	else 	if (umovestr(tcp, addr, n, path) < 0)
42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		path[n] = '\0';
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		string_quote(path);
43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
43376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
43476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintstr(tcp, addr, len)
43776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
43876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
44176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str = NULL;
44276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
44376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, c, usehex;
44476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s, *outend;
445a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath	int trunc;
44676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
44776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
44876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
44976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
45076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
45176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!str) {
452a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath		if ((str = malloc(max_strlen + 1)) == NULL
453779c466c0fdb4a0e4039d5ed407d1e6f61c23437Roland McGrath		    || (outstr = malloc(4*max_strlen
454779c466c0fdb4a0e4039d5ed407d1e6f61c23437Roland McGrath					+ sizeof "\"\"...")) == NULL) {
45546100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
45676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
45776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
45876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
45976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
460779c466c0fdb4a0e4039d5ed407d1e6f61c23437Roland McGrath	outend = outstr + max_strlen * 4;
46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
462a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath		n = max_strlen + 1;
46376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (umovestr(tcp, addr, n, (char *) str) < 0) {
46476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
469a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath		n = MIN(len, max_strlen + 1);
47076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (umoven(tcp, addr, n, (char *) str) < 0) {
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
47476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
47576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
476a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath	trunc = n > max_strlen && str[--n] != 0;
477a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath
47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	usehex = 0;
47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (xflag > 1)
48076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		usehex = 1;
48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (xflag) {
48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < n; i++) {
48376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			c = str[i];
48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (len < 0 && c == '\0')
48576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
48676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!isprint(c) && !isspace(c)) {
48776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				usehex = 1;
48876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
49076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	s = outstr;
49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*s++ = '\"';
49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (usehex) {
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < n; i++) {
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			c = str[i];
49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (len < 0 && c == '\0')
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sprintf(s, "\\x%02x", c);
50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			s += 4;
50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (s > outend)
50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < n; i++) {
50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			c = str[i];
51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (len < 0 && c == '\0')
51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (c) {
51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\"': case '\'': case '\\':
51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = c; break;
51576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\f':
51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = 'f'; break;
51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\n':
51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = 'n'; break;
51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\r':
52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = 'r'; break;
52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\t':
52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = 't'; break;
52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case '\v':
52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = '\\'; *s++ = 'v'; break;
52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(c))
52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = c;
52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else if (i < n - 1 && isdigit(str[i + 1])) {
52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					sprintf(s, "\\%03o", c);
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					s += 4;
53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else {
53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					sprintf(s, "\\%o", c);
53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					s += strlen(s);
53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (s > outend)
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*s++ = '\"';
544a503dcf82047ecf3d8c535406898f3059e424131Roland McGrath	if (i < len || (len < 0 && (trunc || s > outend))) {
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = '.'; *s++ = '.'; *s++ = '.';
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*s = '\0';
54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
5511d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
5521d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
5531d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesdumpiov(tcp, len, addr)
5541d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesstruct tcb * tcp;
5551d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesint len;
5561d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hugheslong addr;
5571d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
5584ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
5594ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
5604ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
5614ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
5624ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
5634ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
5644ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
5654ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5664ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
5674ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
5684ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5694ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
5704ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
5714ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
5724ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
5734ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
5741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
5754ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
5764ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
5774ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
5784ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
5791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
580aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
5811d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
5824ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
5834ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
5844ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
585aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
5861d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
5871d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
588aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
5891d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
5901d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        /* include the buffer number to make it easy to
5911d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                         * match up the trace with the source */
5921d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        tprintf(" * %lu bytes in buffer %d\n",
5934ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                (unsigned long)iov_iov_len(i), i);
5944ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                        dumpstr(tcp, (long) iov_iov_base(i),
5954ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                iov_iov_len(i));
5961d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                }
5971d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
5981d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
5994ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6004ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6014ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6024ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6031d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6041d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6051d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandumpstr(tcp, addr, len)
60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
61376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
62246100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumoven(tcp, addr, len, laddr)
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
6795daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
6925daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
6965daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			/* But if not started, we had a bogus address. */
6971c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
6981c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("ptrace: umoven");
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
7015daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
7095daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
7131c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
7144db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath				perror("ptrace: umoven");
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
7175daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !oldway */
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_READDATA, pid,
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			   (char *) addr, len, laddr) < 0) {
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven: ptrace(PTRACE_READDATA, ...)");
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			abort();
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !oldway */
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
774bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
775ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
776aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
7779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
778aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
780aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
781aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
783bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumovestr(tcp, addr, len, laddr)
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
799bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
800aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
801aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
802aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
803aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
804aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
805aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
806aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
807aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
808aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
809aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
810aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
811aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
812aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int page = 1024; 	/* How to find this? */
813aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
814aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
815aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
816aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
817aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
818aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
819aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
8209cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
821aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
822aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (memchr (laddr, 0, move)) break;
823aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
824aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
825aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
826aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
827aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
828bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
8295daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8445daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8481c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8491c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8525daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8635daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8671c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8681c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8715daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
879bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
880aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
8846d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if !defined (SPARC) && !defined(SPARC64)
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITETEXT	101
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITEDATA	102
8876d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 */
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuload(cmd, pid, addr, len, laddr)
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint cmd;
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: ptrace(PTRACE_WRITE, ...)");
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(peek, pid, (char *) addr, 0);
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			u.val = ptrace(peek, pid, (char *) addr, 0);
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantload(pid, addr, len, laddr)
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr, len;
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandload(pid, addr, len, laddr)
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr;
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
982bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanupeek(pid, off, res)
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong off;
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong *res;
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1005d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				extern const struct xlat struct_user_offsets[];
1006d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (val == -1 && errno) {
10191e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath		char buf[60];
10200e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
10211e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath		perror(buf);
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1028bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1030a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#if 0
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangetpc(tcp)
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1038f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#if defined(I386)
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &pc) < 0)
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
10410e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
10420e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &pc) < 0)
10430e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
10448b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#elif defined(IA64)
10458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	if (upeek(tcp->pid, PT_B0, &pc) < 0)
10468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return -1;
1047f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ARM)
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*15, &pc) < 0)
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1050f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(POWERPC)
1051eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
105384fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1056f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ALPHA)
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0)
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1059f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
1060f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman 	if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1061f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman 		return -1;
10626d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	pc = regs.r_pc;
106710a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
10684dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman	if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
106910a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig		return -1;
1070c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1071c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1072c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1073ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1074ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1075ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
1076f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1077e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath       if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1078e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath               return -1;
10797a0b649aeace5c1e1efe4a1d7b1ae6e3a87e0d44Wichert Akkerman#endif
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return pc;
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Return current program counter for `pid'
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Assumes PC is never 0xffffffff
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getpc: ptrace(PTRACE_GETREGS, ...)");
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return regs.r_pc;
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	return regs.r_eip;
1106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
1108a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#endif
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintcall(tcp)
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
11147a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
11157a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
11167a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
11237a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1127eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
1128eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif defined(S390) || defined(S390X)
1129eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         long psw;
1130eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
11317a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath                 PRINTBADPC;
1132eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath                 return;
1133eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         }
1134eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#ifdef S390
1135eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         tprintf("[%08lx] ", psw);
1136eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif S390X
1137eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath       tprintf("[%16lx] ", psw);
1138eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#endif
1139eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
11400e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
11410e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
11420e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
11430e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
11447a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
11450e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
11460e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
11470e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
1148ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(IA64)
11498b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
11508b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
11518b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	if (upeek(tcp->pid, PT_B0, &ip) < 0) {
11527a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
11538b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
11548b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
11558b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
1156faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1159eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
116484fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
1172faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
11767a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11806d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
11819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
11837a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tprintf("[%08lx] ", regs.r_pc);
1187c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1188c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1189c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1190c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1191c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		tprintf ("[????????] ");
1192c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1193c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1194c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
119575c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman#elif defined(MIPS)
119675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
119775c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
119875c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
119975c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		tprintf ("[????????] ");
120075c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
120175c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
120275c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
1203ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1204ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1205ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1206ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1207ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               tprintf ("[????????] ");
1208ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return;
1209ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       }
1210ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       tprintf("[%08lx] ", pc);
1211f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1212e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1213e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1214e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
12157a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
1216e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1217e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1218e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
1219ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(ARM)
1220ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1221e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1222ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	if (upeek(tcp->pid, 4*15, &pc) < 0) {
12237a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1224ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1225ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1226ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
1227faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* !architecture */
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
12357a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
12437a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1246bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1247bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1248bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1250bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1255d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#if defined LINUX
1256d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1257d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#include <sys/syscall.h>
1258d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifndef CLONE_PTRACE
1259d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define CLONE_PTRACE    0x00002000
1260d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
126176989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#ifndef CLONE_STOPPED
126276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath# define CLONE_STOPPED   0x02000000
126376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#endif
1264d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1265d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef IA64
1266d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
126708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
126808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
126908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_fork	2
127008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_vfork	190
127108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1272d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1273d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1274d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1275d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1276d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1277d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	unsigned long *bsp, cfm, sof, sol;
1278d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
127908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
128008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
128108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1282d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1283d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1284d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1285d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1286d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1287d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1288d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
1289d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1290d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1291d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	*state = bsp;
1292d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1293d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1294d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1295d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1296d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1297d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1298d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1299d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1300d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
130108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
130208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
130308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
130408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = upeek (tcp->pid, PT_R11, valp);
130508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
130608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
130708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
130808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
130908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1310d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1311d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1312d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1313d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1314d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
131508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
131608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
131708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
131808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = upeek (tcp->pid, PT_R9, valp);
131908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
132008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
132108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
132208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
132308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1324d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1325d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1326d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1327d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1328d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1329d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
133008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
133108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
133208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
133308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
133408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
133508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
133608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
133708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1338d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
133908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1340d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1341d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1342d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1343d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1344d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1345d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
134608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
134708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
134808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
134908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
135008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
135108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
135208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
135308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1354d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
135508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1356d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1357d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1358d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13596d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined (SPARC) || defined (SPARC64)
1360d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1361d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef struct regs arg_setup_state;
1362d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1363d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) \
1364d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1365d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state) \
1366d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1367d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1368d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1369d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1370d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1371d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1372e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) 0
1373d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1374d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1375d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1376d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# if defined S390 || defined S390X
13777b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
13787b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
13797b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
13807b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
13817b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg0_offset	PT_GPR3
13827b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg1_offset	PT_ORIGGPR2
13837b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
13847b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg1(tcp, state, val) ((void) (state), 0)
1385c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg0_index	1
1386c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg1_index	0
1387d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (ALPHA) || defined (MIPS)
1388d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	REG_A0
1389d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	(REG_A0+1)
1390d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (POWERPC)
1391eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg0_offset	(sizeof(unsigned long)*PT_R3)
1392eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg1_offset	(sizeof(unsigned long)*PT_R4)
13937b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
1394d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (HPPA)
1395d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	 PT_GR26
1396d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	 (PT_GR26-4)
13977f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath# elif defined (X86_64)
13987f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
13997f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
1400ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath# elif defined (SH)
1401ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg0_offset	(4*(REG_REG0+4))
1402ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg1_offset	(4*(REG_REG0+5))
1403f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath# elif defined (SH64)
1404e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath   /* ABI defines arg0 & 1 in r2 & r3 */
1405e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg0_offset   (REG_OFFSET+16)
1406e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg1_offset   (REG_OFFSET+24)
1407e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define restore_arg0(tcp, state, val) 0
1408d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# else
1409d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	0
1410d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	4
1411ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  if defined ARM
1412e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#   define restore_arg0(tcp, state, val) 0
1413e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#  endif
1414d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# endif
1415d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1416d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1417d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1418d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) (0)
1419d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1420d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, cookie, valp) \
1421d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (upeek ((tcp)->pid, arg0_offset, (valp)))
1422d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, cookie, valp) \
1423d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (upeek ((tcp)->pid, arg1_offset, (valp)))
1424d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1425d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1426d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, void *cookie, long val)
1427d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1428ca85b97c9cea63db45e59a345218b902936b693dRoland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1429d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1430d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1431d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1432d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, void *cookie, long val)
1433d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1434d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1435d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1436d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1437d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1438d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1439e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg0
1440e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1441e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1442e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg1
1443e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1444e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1445d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
144690d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#ifndef arg0_index
144790d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg0_index 0
144890d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg1_index 1
144990d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#endif
145090d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1451d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1452d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathsetbpt(tcp)
1453d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1454d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1455d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	extern int change_syscall(struct tcb *, int);
1456d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1457d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1458d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1459d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1460d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1461d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1462d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
146376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
14649383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#ifdef SYS_vfork
14659383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
14669383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#endif
1467d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1468d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
14699b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#endif
14709b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#if defined SYS_fork || defined SYS_vfork
1471d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		if (arg_setup (tcp, &state) < 0
1472d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1473d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1474d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || change_syscall(tcp, SYS_clone) < 0
1475d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1476d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg1 (tcp, &state, 0) < 0
1477d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || arg_finish_change (tcp, &state) < 0)
1478d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1479c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1480c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1481d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1482d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1483d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1484d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1485d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone:
1486d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_clone2
1487d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone2:
1488d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
148902cee8d5cbcb0aaaf64d4f4d0916e3d4dbd8ee01Roland McGrath		if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1490d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    && (arg_setup (tcp, &state) < 0
1491c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath			|| set_arg0 (tcp, &state,
1492c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath				     tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1493d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			|| arg_finish_change (tcp, &state) < 0))
1494d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1495d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1496c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1497c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1498d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1499d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1500d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1501d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1502d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1503d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1504d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1505d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1506d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1507d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1508d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1509d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1510d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathclearbpt(tcp)
1511d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1512d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1513d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1514d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (arg_setup (tcp, &state) < 0
1515e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1516e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1517d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	    || arg_finish_change (tcp, &state))
1518d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1519d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1520d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1521d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1522d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1523d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1524d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermansetbpt(tcp)
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
15316d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* We simply use the SunOS breakpoint code. */
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
15356d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	unsigned long inst;
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
15469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop instead, in expectance of the SIGSTOP
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
15656d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst = LOOPA;
15666d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC64)
15676d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst <<= 32;
15686d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst |= (tcp->inst[0] & 0xffffffffUL);
15696d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif
15706d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15776d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !SPARC && !SPARC64 */
15788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#ifdef IA64
15797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
15807b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#		define LOOP	0x0000feeb
15817b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (tcp->flags & TCB_BPTSET) {
15827b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: bpt already set in pid %u\n",
15837b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid);
15847b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
15857b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
15867b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
15877b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
15887b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
15897b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] setting bpt at %lx\n",
15907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid, tcp->baddr);
15917b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
15927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      (char *) tcp->baddr, 0);
15937b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
15947b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
15957b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
15967b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
15977b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
15987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
15997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
16007b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
16017b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
16027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags |= TCB_BPTSET;
16037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
16047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/*
16057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * Our strategy here is to replace the bundle that
16067b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * contained the clone() syscall with a bundle of the
16077b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * form:
16087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
16097b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *	{ 1: br 1b; br 1b; br 1b }
16107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
16117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * This ensures that the newly forked child will loop
16127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * endlessly until we've got a chance to attach to it.
16137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 */
16148b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP0	0x0000100000000017
16158b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP1	0x4000000000200000
16168b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
16178b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
16188b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
16198b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
16208b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
16218b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16228b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IIP, &addr) < 0)
16238b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/* store "ri" in low two bits */
16257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->baddr = addr | ((ipsr >> 41) & 0x3);
16268b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
16278b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
16287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
16297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
16307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
16317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
16328b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
16338b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
16348b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16358b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
16368b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
16378b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
16388b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
16398b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
16408b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
16418b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
16428b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
16438b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
16448b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags |= TCB_BPTSET;
16458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
16468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#else /* !IA64 */
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16480e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined (I386) || defined(X86_64)
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x0000feeb
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x60fe0000
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
16534dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xc3ffffff
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
16551e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath#define LOOP	0x48000000
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined(ARM)
16579a8a37f2b28d1c0d3f57951fd5aeeb96ff7d2f16Wichert Akkerman#define LOOP	0xEAFFFFFE
1658f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
16594dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0x1000ffff
16604dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#elif defined(S390)
16614dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xa7f40000	/* BRC 15,0 */
166210a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390X)
166310a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1664c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1665c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */
1666ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1667ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#ifdef __LITTLE_ENDIAN__
1668ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0x0000affe
1669ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#else
1670ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0xfeaf0000
1671ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#endif
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined (I386)
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
16830e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined (X86_64)
16840e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
16850e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	  return -1;
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ARM)
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
1693f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined (MIPS)
1694f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman	return -1;		/* FIXME: I do not know what i do - Flo */
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
1696eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
169810a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
16994dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman	if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
17004dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman		return -1;
1701c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1702c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1703c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1704c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tcp->baddr &= ~0x03;
1705ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1706ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1707ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17258b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif /* !IA64 */
17266d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* SPARC || SPARC64 */
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC	/* This code is slightly sparc specific */
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1732e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define BPT	0x91d02001	/* ta	1 */
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x10800000	/* ba	0 */
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define NOP	0x01000000
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if LOOPA
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *)tcp->inst) < 0) {
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanclearbpt(tcp)
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
17870e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined(I386) || defined(X86_64)
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
1789faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1791faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1793faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1795c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1796c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long iaoq;
1797ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1798ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1799faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* architecture */
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18016d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Again, we borrow the SunOS breakpoint code. */
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
1814faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(IA64)
18157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
18167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		unsigned long addr;
18177b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
18187b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
18197b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
18207b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (!(tcp->flags & TCB_BPTSET)) {
18217b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
18227b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
18237b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
18247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		errno = 0;
18257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
18267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
18277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
18287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
18297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
18307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
18317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
18327b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
18337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
18347b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (addr != tcp->baddr) {
18357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			/* The breakpoint has not been reached yet.  */
18367b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			if (debug)
18377b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				fprintf(stderr,
18387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
18397b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman						addr, tcp->baddr);
18407b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return 0;
18417b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
18427b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
18438b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
18448b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
18458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
18478b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18488b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
18498b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18508b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (upeek(pid, PT_CR_IIP, &addr) < 0)
18518b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18528b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18538b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original bundle: */
18548b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
18558b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
18568b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
18578b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
18588b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
18598b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18608b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
18618b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18628b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original "ri" in ipsr: */
18638b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
18648b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
18658b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
18668b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
18678b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
18688b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18698b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
18708b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18718b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
18728b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18738b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (addr != (tcp->baddr & ~0x3)) {
18748b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			/* the breakpoint has not been reached yet.  */
18758b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			if (debug)
18768b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman				fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
18778b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman					addr, tcp->baddr);
18788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return 0;
18798b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
18808b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
18816d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !IA64  && !SPARC && !SPARC64 */
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*EIP, &eip) < 0)
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (eip != tcp->baddr) {
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					eip, tcp->baddr);
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
19080e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
19090e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (upeek(tcp->pid, 8*RIP, &eip) < 0)
19100e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
19110e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (eip != tcp->baddr) {
19120e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		/* The breakpoint has not been reached yet.  */
19130e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		if (debug)
19140e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig			fprintf(stderr,
19150e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
19160e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig					eip, tcp->baddr);
19170e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return 0;
19180e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
1919c792698a99b640e7d256e8692c992bd967f0c5b2Wichert Akkerman#elif defined(POWERPC)
1920eb285359906700f46b22cf4f9911695034313736Roland McGrath	if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1929faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1939faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (upeek(tcp->pid, REG_PC, &pc) < 0)
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1949c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1950c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1951c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1952c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq &= ~0x03;
1953c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1954c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		/* The breakpoint has not been reached yet.  */
1955c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		if (debug)
1956c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1957c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman				iaoq, tcp->baddr);
1958c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return 0;
1959c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1960c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq = tcp->baddr | 3;
1961c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	/* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1962c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1963c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * has no significant effect.
1964c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 */
1965c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1966c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1967ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1968ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1969ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
1970ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        if (pc != tcp->baddr) {
1971ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                /* The breakpoint has not been reached yet.  */
1972ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                if (debug)
1973ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                        fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1974ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                                pc, tcp->baddr);
1975ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                return 0;
1976ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        }
1977ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1978faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* arch */
19796d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 && !IA64 */
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
1986e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * to adjust the program counter after removing the our `breakpoint'.
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((regs.r_pc < tcp->baddr) ||
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(regs.r_pc > tcp->baddr + 4)) {
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					regs.r_pc, tcp->parent->baddr);
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LOOPA */
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2035d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
2036d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
2037bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangetex(pid, hdr)
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct exec *hdr;
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfixvfork(tcp)
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getex(pid, &hdr) < 0)
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
209246100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[symbol: %s]\n", cp);
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
2133