util.c revision 732d1bf4d4aaff68eff1c41d8900264637a57dfe
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/*
244732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Generic ptrace wrapper which tracks ESRCH errors
245732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * by setting tcp->ptrace_errno to ESRCH.
246732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko *
247732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * We assume that ESRCH indicates likely process death (SIGKILL?),
248732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * modulo bugs where process somehow ended up not stopped.
249732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Unfortunately kernel uses ESRCH for that case too. Oh well.
250732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko *
251732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Currently used by upeek() only.
252732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * TODO: use this in all other ptrace() calls while decoding.
253732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
254732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkolong
255732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkodo_ptrace(int request, struct tcb *tcp, void *addr, void *data)
256732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
257732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	long l;
258732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
259732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
260732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	l = ptrace(request, tcp->pid, addr, data);
261732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	/* Non-ESRCH errors might be our invalid reg/mem accesses,
262732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	 * we do not record them. */
263732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (errno == ESRCH)
264732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		tcp->ptrace_errno = ESRCH;
265732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return l;
266732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
267732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
268732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
269732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Used when we want to unblock stopped traced process.
270732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
271732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Returns 0 on success or if error was ESRCH
272732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * (presumably process was killed while we talk to it).
273732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Otherwise prints error message and returns -1.
274732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
275732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkoint
276732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkoptrace_restart(int op, struct tcb *tcp, int sig)
277732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
278732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	int err;
279732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	const char *msg;
280732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
281732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
282732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	ptrace(op, tcp->pid, (void *) 1, (void *) (long) sig);
283732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	err = errno;
284732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (!err || err == ESRCH)
285732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		return 0;
286732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
287732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	tcp->ptrace_errno = err;
288732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	msg = "SYSCALL";
289732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (op == PTRACE_CONT)
290732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		msg = "CONT";
291732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (op == PTRACE_DETACH)
292732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		msg = "DETACH";
293732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
294732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			msg, sig, strerror(err));
295732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return -1;
296732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
297732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
298732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
302ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
304ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", str);
30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
30976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanaddflags(xlat, flags)
319d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n++;
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
338a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
339a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Interpret `xlat' as an array of flags/
340a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
341a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
342a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
343a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
344a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
345a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
346a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
347a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
348a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
349a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	strcpy(outstr, prefix);
350a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
351a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
352a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
353a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
354a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath				strcat(outstr, "|");
355a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, xlat->str);
356a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			flags &= ~xlat->val;
357a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
358a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
359a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
360a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
361a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
362a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, "|");
363a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		sprintf(outstr + strlen(outstr), "%#x", flags);
364a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
365a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
366a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
367a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
368a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
370b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathprintflags(xlat, flags, dflt)
371d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
373b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathconst char *dflt;
37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *sep;
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
392b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
393b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
394b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
395b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
396b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
397b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
398b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
399b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
400b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
401b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
402b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
403b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
404b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
405b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
406b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
40776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
408b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintnum(tcp, addr, fmt)
41476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
418eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
42376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
42476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
42576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
4336bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
4349814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathprintnum_int(tcp, addr, fmt)
4359814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathstruct tcb *tcp;
4369814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathlong addr;
4379814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathchar *fmt;
4389814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
4399814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
4409814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4419814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
4429814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
4439814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4449814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
4459814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
4469814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
4479814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4489814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
4499814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
4509814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
4519814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
4529814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
4539814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4549814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4556bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathprintuid(text, uid)
4566bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathconst char *text;
4576bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathunsigned long uid;
4586bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4596bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
4606bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
4616bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4626bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
46376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
46476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
465a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
466a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
467a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
468a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat `instr' as a NUL-terminated string
469a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
470a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
4716d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrathstatic int
472bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinstring_quote(const char *instr, char *outstr, int len, int size)
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
475bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
476bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	int usehex = 0, c, i;
47776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
478bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
479bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
480bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
481a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
482a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
483bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
484bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
485a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
486a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
487a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
488a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
489a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
490a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
491a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
492a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
493bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
494bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
495bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
496bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
497bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
500bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
502bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
503a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
505bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
506a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
507a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
508a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
509a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
510a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
511a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
512a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
513a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			sprintf(s, "\\x%02x", c);
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			s += 4;
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
518bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
520a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
521a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
522a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
523a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
524a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
525a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
526a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
527a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
528bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
529bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
530bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
531bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
532bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
533bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
534bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
535bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
536bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
537bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
538bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
539bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
540bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
541bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
542bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
543bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
544bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
545bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
546bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
547bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
548bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
549bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
550bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
551bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
552bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
553bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
554bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
555bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
556bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					else if (i + 1 < size
557bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						 && isdigit(ustr[i + 1])) {
558bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%03o", c);
559bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += 4;
560bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					} else {
561bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%o", c);
562bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += strlen(s);
563bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
564bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
565bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
569bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
570bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
5716d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
5726d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	/* Return nonzero if the string was unterminated.  */
5736d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	return i == size;
57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
576a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
577a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
578a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
579a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
581bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
583a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
584371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
585bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
586bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
587bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
588a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Cap path length to the path buffer size,
589a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	   and NUL-terminate the buffer. */
590a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
591a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
592bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	path[n] = '\0';
593a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
594a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
595bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (umovestr(tcp, addr, n + 1, path) < 0)
59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
598bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
599bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		int trunc = (path[n] != '\0');
600bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
601bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (trunc)
602bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			path[n] = '\0';
603a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		(void) string_quote(path, outstr, -1, n + 1);
604a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		if (trunc)
605bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			strcat(outstr, "...");
606bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		tprintf("%s", outstr);
60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
611bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
612bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
613bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	printpathn(tcp, addr, sizeof path - 1);
614bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
615bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
616a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
617a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
618a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
619a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
620a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
621bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
622bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintstr(struct tcb *tcp, long addr, int len)
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
624bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
6266d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
632a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
633a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str)
634a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
635a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!outstr)
636a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		outstr = malloc(4 * max_strlen + sizeof "\"...\"");
637a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str || !outstr) {
638a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		fprintf(stderr, "out of memory\n");
639a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		tprintf("%#lx", addr);
640a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		return;
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
642bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
644a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
645a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
646a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
647a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
648bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
649a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str[max_strlen] = '\0';
650bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
656a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		size = MIN(len, max_strlen);
657bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
663a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (string_quote(str, outstr, len, size) &&
664a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	    (len < 0 || len > max_strlen))
665bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		strcat(outstr, "...");
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6701d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6711d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6721d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesdumpiov(tcp, len, addr)
6731d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesstruct tcb * tcp;
6741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesint len;
6751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hugheslong addr;
6761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6774ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
6784ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6794ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6804ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6814ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6824ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6834ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6844ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6854ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6864ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6874ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6884ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6894ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6904ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6914ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6924ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6931d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6944ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6954ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6964ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6974ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6981d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
699aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
7001d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
7014ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
7024ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
7034ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
704aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
7051d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
7061d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
707aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
7081d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
7091d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        /* include the buffer number to make it easy to
7101d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                         * match up the trace with the source */
7111d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                        tprintf(" * %lu bytes in buffer %d\n",
7124ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                (unsigned long)iov_iov_len(i), i);
7134ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                        dumpstr(tcp, (long) iov_iov_base(i),
7144ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin                                iov_iov_len(i));
7151d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes                }
7161d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
7171d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
7184ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
7194ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
7204ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
7214ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
7221d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
7231d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
7241d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandumpstr(tcp, addr, len)
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
74146100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumoven(tcp, addr, len, laddr)
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
7985daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8115daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8155daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			/* But if not started, we had a bogus address. */
8161c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8171c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("ptrace: umoven");
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8205daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
8285daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8321c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
8334db2624c8f6ec2c6f204c945df349bf42a897d01Roland McGrath				perror("ptrace: umoven");
83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
8365daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven");
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !oldway */
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_READDATA, pid,
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			   (char *) addr, len, laddr) < 0) {
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("umoven: ptrace(PTRACE_READDATA, ...)");
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			abort();
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !oldway */
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
893bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
894ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
895aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
8969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
897aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
899aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
900aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
902bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanumovestr(tcp, addr, len, laddr)
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
918bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
919aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
920aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
921aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
922aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
923aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
924aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
925aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
926aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
927aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
928aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
929aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
930aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
931aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int page = 1024; 	/* How to find this? */
932aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
933aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
934aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
935aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
936aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
937aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
938aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
9399cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
940aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
941aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (memchr (laddr, 0, move)) break;
942aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
943aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
944aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
945aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
946aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
947bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
9485daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
9635daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
9671c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
9681c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
9715daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
9825daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman			if (started && (errno==EPERM || errno==EIO)) {
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Ran into 'end of memory' - stupid "printpath" */
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
9861c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath			if (addr != 0 && errno != EIO)
9871c459769f69ff7cac0e12f934517e1ab349b9cc0Roland McGrath				perror("umovestr");
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
9905daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
998bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
999aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
10036d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if !defined (SPARC) && !defined(SPARC64)
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITETEXT	101
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PTRACE_WRITEDATA	102
10066d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 */
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuload(cmd, pid, addr, len, laddr)
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint cmd;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: ptrace(PTRACE_WRITE, ...)");
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		errno = 0;
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		u.val = ptrace(peek, pid, (char *) addr, 0);
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (errno) {
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			u.val = ptrace(peek, pid, (char *) addr, 0);
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("uload: POKE");
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantload(pid, addr, len, laddr)
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr, len;
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandload(pid, addr, len, laddr)
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint addr;
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *laddr;
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1101bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1104932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkoupeek(tcp, off, res)
1105932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkostruct tcb *tcp;
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong off;
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong *res;
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1124d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				extern const struct xlat struct_user_offsets[];
1125d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
1136732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (val == -1 && errno) {
1138732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (errno != ESRCH) {
1139732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			char buf[60];
1140732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1141732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			perror(buf);
1142732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1151a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#if 0
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangetpc(tcp)
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1159f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#if defined(I386)
1160932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &pc) < 0)
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
11620e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
1163932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &pc) < 0)
11640e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
11658b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#elif defined(IA64)
1166932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_B0, &pc) < 0)
11678b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return -1;
1168f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ARM)
1169932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*15, &pc) < 0)
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin#elif defined(BFIN)
1172932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0)
117387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return -1;
1174f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(POWERPC)
1175932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117784fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
1178932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0)
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1180f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(ALPHA)
1181932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0)
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1183f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
1184932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko 	if (upeek(tcp, REG_EPC, &pc) < 0)
1185f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman 		return -1;
11866d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
11879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
11909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	pc = regs.r_pc;
119110a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
1192932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if(upeek(tcp,PT_PSWADDR,&pc) < 0)
119310a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig		return -1;
1194c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1195932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if(upeek(tcp,PT_IAOQ0,&pc) < 0)
1196c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1197ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1198932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko       if (upeek(tcp, 4*REG_PC ,&pc) < 0)
1199ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
1200f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1201932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko       if (upeek(tcp, REG_PC ,&pc) < 0)
1202e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath               return -1;
12037a0b649aeace5c1e1efe4a1d7b1ae6e3a87e0d44Wichert Akkerman#endif
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return pc;
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Return current program counter for `pid'
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Assumes PC is never 0xffffffff
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getpc: ptrace(PTRACE_GETREGS, ...)");
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return regs.r_pc;
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	return regs.r_eip;
1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
1232a4d4853f679014799a6608cc8114e6ce7f37ae89Roland McGrath#endif
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintcall(tcp)
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
12387a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
12397a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
12407a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1246932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &eip) < 0) {
12477a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1251eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
1252eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif defined(S390) || defined(S390X)
1253eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         long psw;
1254932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko         if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
12557a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath                 PRINTBADPC;
1256eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath                 return;
1257eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         }
1258eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#ifdef S390
1259eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath         tprintf("[%08lx] ", psw);
1260eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#elif S390X
1261eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath       tprintf("[%16lx] ", psw);
1262eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath#endif
1263eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
12640e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
12650e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
12660e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
1267932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &rip) < 0) {
12687a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
12690e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
12700e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
12710e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
1272ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(IA64)
12738b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
12748b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
1275932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_B0, &ip) < 0) {
12767a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
12778b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
12788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
12798b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
1280faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1283932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
128884fa923c15aa537b666d26694549091e9b9a5ddbRoland McGrath#elif defined(M68K)
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1291932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0) {
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
1296faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1299932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
13007a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
13046d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined(SPARC) || defined(SPARC64)
13059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
13077a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tprintf("[%08lx] ", regs.r_pc);
1311c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1312c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1313c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1314932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
1315c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		tprintf ("[????????] ");
1316c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1317c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1318c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
131975c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman#elif defined(MIPS)
132075c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
132175c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
1322932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_EPC, &pc) < 0) {
132375c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		tprintf ("[????????] ");
132475c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
132575c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
132675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
1327ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1328ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1329ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1330932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko       if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1331ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               tprintf ("[????????] ");
1332ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return;
1333ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       }
1334ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       tprintf("[%08lx] ", pc);
1335f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath#elif defined(SH64)
1336e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1337e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1338932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
13397a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
1340e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1341e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1342e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
1343ef388689610fa17df1d3001face8057b411a2e26Roland McGrath#elif defined(ARM)
1344ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1345e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1346932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*15, &pc) < 0) {
13477a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1348ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1349ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1350ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
135187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin#elif defined(BFIN)
135287ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	long pc;
135387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin
1354932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_PC, &pc) < 0) {
135587ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		PRINTBADPC;
135687ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return;
135787ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	}
135887ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	tprintf("[%08lx] ", pc);
1359faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* !architecture */
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
13677a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
13757a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1378bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1381bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1387d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#if defined LINUX
1388d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13893291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath#include "syscall.h"
13903291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
1391d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#include <sys/syscall.h>
1392d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifndef CLONE_PTRACE
1393d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define CLONE_PTRACE    0x00002000
1394d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1395d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath#ifndef CLONE_VFORK
1396d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath# define CLONE_VFORK     0x00004000
1397d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath#endif
13988fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil#ifndef CLONE_VM
13998fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil# define CLONE_VM        0x00000100
14008fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil#endif
140176989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#ifndef CLONE_STOPPED
140276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath# define CLONE_STOPPED   0x02000000
140376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath#endif
1404d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1405d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef IA64
1406d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
140708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
140808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
140908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_fork	2
141008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath#define SYS_vfork	190
141108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1412d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1413d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1414d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1415d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1416d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
14171f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
14181f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1419d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14201f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
14211f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
14221f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
142308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
14241f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
142508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1426932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1427d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1428932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1429d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1430d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1431d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1432d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
14331f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1434d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14351f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1436d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1437d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1438d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1439d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1440d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1441d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1442d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1443d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1444d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
144508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
144608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
144708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1448932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		ret = upeek (tcp, PT_R11, valp);
144908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
145008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
145108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
145208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
145308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1454d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1455d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1456d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1457d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1458d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
145908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
146008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
146108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1462932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		ret = upeek (tcp, PT_R9, valp);
146308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
146408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
146508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
146608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
146708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1468d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1469d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1470d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1471d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1472d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1473d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
147408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
147508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
147608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
147708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
147808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
147908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
148008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
148108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1482d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
148308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1484d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1485d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1486d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1487d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1488d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1489d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
149008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
149108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
149208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
149308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
149408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
149508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
149608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
149708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1498d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	errno = 0;
149908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1500d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return errno ? -1 : 0;
1501d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1502d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1503b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1504b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1505b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
1506b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath# define restore_arg0(tcp, state, val) ((void) (state), 0)
1507b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath# define restore_arg1(tcp, state, val) ((void) (state), 0)
1508b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
15096d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#elif defined (SPARC) || defined (SPARC64)
1510d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1511d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef struct regs arg_setup_state;
1512d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1513d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) \
1514d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1515d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state) \
1516d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath  (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1517d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1518d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1519d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1520d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1521d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1522e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) 0
1523d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1524d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1525d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1526d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# if defined S390 || defined S390X
15277b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
15287b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
15297b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
15307b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
15317b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg0_offset	PT_GPR3
15327b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define arg1_offset	PT_ORIGGPR2
15337b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
15347b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg1(tcp, state, val) ((void) (state), 0)
1535c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg0_index	1
1536c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath#  define arg1_index	0
1537d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (ALPHA) || defined (MIPS)
1538d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	REG_A0
1539d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	(REG_A0+1)
1540d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (POWERPC)
1541eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg0_offset	(sizeof(unsigned long)*PT_R3)
1542eb285359906700f46b22cf4f9911695034313736Roland McGrath#  define arg1_offset	(sizeof(unsigned long)*PT_R4)
15437b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath#  define restore_arg0(tcp, state, val) ((void) (state), 0)
1544d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# elif defined (HPPA)
1545d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	 PT_GR26
1546d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	 (PT_GR26-4)
15477f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath# elif defined (X86_64)
15487f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
15497f33cc3eb5ead7a79cae8c586e40d2f8b573eec1Roland McGrath#  define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
1550ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath# elif defined (SH)
1551ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg0_offset	(4*(REG_REG0+4))
1552ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  define arg1_offset	(4*(REG_REG0+5))
1553f5a477788ed49d3c15e2080c03d30d4beaeefee3Roland McGrath# elif defined (SH64)
1554e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath   /* ABI defines arg0 & 1 in r2 & r3 */
1555e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg0_offset   (REG_OFFSET+16)
1556e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define arg1_offset   (REG_OFFSET+24)
1557e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath#  define restore_arg0(tcp, state, val) 0
1558d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# else
1559d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg0_offset	0
1560d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#  define arg1_offset	4
1561ac971c27278e1d45bf12c1ba522c7507ba778144Roland McGrath#  if defined ARM
1562e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#   define restore_arg0(tcp, state, val) 0
1563e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#  endif
1564d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# endif
1565d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1566d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1567d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1568d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_setup(tcp, state) (0)
1569d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define arg_finish_change(tcp, state)	0
1570d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg0(tcp, cookie, valp) \
1571932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko  (upeek ((tcp), arg0_offset, (valp)))
1572d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# define get_arg1(tcp, cookie, valp) \
1573932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko  (upeek ((tcp), arg1_offset, (valp)))
1574d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1575d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1576d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, void *cookie, long val)
1577d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1578ca85b97c9cea63db45e59a345218b902936b693dRoland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1579d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1580d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1581d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1582d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, void *cookie, long val)
1583d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1584d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1585d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1586d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1587d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1588d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1589e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg0
1590e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1591e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1592e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#ifndef restore_arg1
1593e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1594e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath#endif
1595d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
159690d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#ifndef arg0_index
159790d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg0_index 0
159890d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath# define arg1_index 1
159990d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath#endif
160090d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1601d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1602d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathsetbpt(tcp)
1603d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1604d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
16053291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1606d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	extern int change_syscall(struct tcb *, int);
1607d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1608d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1609d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1610d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1611d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1612d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1613d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
16143291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
16153291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
16163291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
16173291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
16183291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
16193291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
16203291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
16213291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
16223291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
16233291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
16243291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
16253291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
16263291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
16273291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
162876989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
16299383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#ifdef SYS_vfork
16309383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
16319383c6c539af09303efe0a16dea55363b095f66eRoland McGrath#endif
1632d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_fork
1633d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
16349b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#endif
16359b0982b5d3b84c845192ad8b7ad822f81cf4743aRoland McGrath#if defined SYS_fork || defined SYS_vfork
1636d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		if (arg_setup (tcp, &state) < 0
1637d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1638d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
16393291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		    || change_syscall(tcp, clone_scno[current_personality]) < 0
1640d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1641d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg1 (tcp, &state, 0) < 0
1642d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || arg_finish_change (tcp, &state) < 0)
1643d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1644c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1645c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1646d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1647d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1648d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
1649d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1650d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone:
1651d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#ifdef SYS_clone2
1652d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone2:
1653d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
16548fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
16558fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   contrary to x86 SYS_vfork above.  Even on x86 we turn the
16568fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
16578fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
16588fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
16598fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
16608fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
16618fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1662d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		if ((arg_setup (tcp, &state) < 0
1663d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || set_arg0 (tcp, &state,
1664d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath				 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
16658fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
16668fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				     ? CLONE_VFORK | CLONE_VM : 0)) < 0
1667d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || arg_finish_change (tcp, &state) < 0))
1668d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    return -1;
1669d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1670c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1671c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1672d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1673d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1674d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1675d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1676d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1677d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1678d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1679d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1680d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1681d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1682d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1683d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1684d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathclearbpt(tcp)
1685d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1686d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1687d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1688d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (arg_setup (tcp, &state) < 0
1689e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1690e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1691d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	    || arg_finish_change (tcp, &state))
1692d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1693d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1694d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1695d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1696d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1697d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#else
1698d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermansetbpt(tcp)
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
17056d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* We simply use the SunOS breakpoint code. */
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct regs regs;
17096d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	unsigned long inst;
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
17209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop instead, in expectance of the SIGSTOP
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
17396d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst = LOOPA;
17406d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC64)
17416d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst <<= 32;
17426d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	inst |= (tcp->inst[0] & 0xffffffffUL);
17436d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif
17446d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17516d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !SPARC && !SPARC64 */
17528b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#ifdef IA64
17537b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
17547b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#		define LOOP	0x0000feeb
17557b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (tcp->flags & TCB_BPTSET) {
17567b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: bpt already set in pid %u\n",
17577b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid);
17587b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
17597b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
1760932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
17617b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
17627b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
17637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] setting bpt at %lx\n",
17647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tcp->pid, tcp->baddr);
17657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
17667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      (char *) tcp->baddr, 0);
17677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
17687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
17697b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
17707b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
17717b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
17727b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
17737b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
17747b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
17757b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
17767b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags |= TCB_BPTSET;
17777b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
17787b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/*
17797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * Our strategy here is to replace the bundle that
17807b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * contained the clone() syscall with a bundle of the
17817b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * form:
17827b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
17837b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *	{ 1: br 1b; br 1b; br 1b }
17847b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 *
17857b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * This ensures that the newly forked child will loop
17867b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 * endlessly until we've got a chance to attach to it.
17877b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		 */
17888b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP0	0x0000100000000017
17898b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#		define LOOP1	0x4000000000200000
17908b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
17918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
17928b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
17938b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
1794932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
17958b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
1796932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IIP, &addr) < 0)
17978b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
17987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		/* store "ri" in low two bits */
17997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->baddr = addr | ((ipsr >> 41) & 0x3);
18008b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18018b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
18027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
18037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
18047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
18057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				      0);
18068b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
18078b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
18088b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18098b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
18108b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
18118b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
18128b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
18138b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
18148b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
18158b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
18168b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
18178b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
18188b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags |= TCB_BPTSET;
18198b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
18208b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#else /* !IA64 */
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18220e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined (I386) || defined(X86_64)
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x0000feeb
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x60fe0000
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
18274dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xc3ffffff
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
18291e85cf9cb1b0cf3773bbd361bce57379d30b4940Roland McGrath#define LOOP	0x48000000
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined(ARM)
18319a8a37f2b28d1c0d3f57951fd5aeeb96ff7d2f16Wichert Akkerman#define LOOP	0xEAFFFFFE
1832f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined(MIPS)
18334dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0x1000ffff
18344dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#elif defined(S390)
18354dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman#define LOOP	0xa7f40000	/* BRC 15,0 */
183610a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390X)
183710a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1838c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1839c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */
1840ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1841ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#ifdef __LITTLE_ENDIAN__
1842ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0x0000affe
1843ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#else
1844ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#define LOOP   0xfeaf0000
1845ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#endif
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined (I386)
1855932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
18570e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined (X86_64)
1858932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
18590e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (M68K)
1861932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	  return -1;
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ALPHA)
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (ARM)
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
1867f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman#elif defined (MIPS)
1868f90da01fd19a7779d6ed9ad66605367ae43bb2fdWichert Akkerman	return -1;		/* FIXME: I do not know what i do - Flo */
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#elif defined (POWERPC)
1870932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
187210a88d09ebe283d0dd2ba5deccfe50dc20ea5821Michal Ludvig#elif defined(S390) || defined(S390X)
1873932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
18744dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman		return -1;
1875c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1876932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
1877c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
1878c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tcp->baddr &= ~0x03;
1879ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1880932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko       if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
1881ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#error unknown architecture
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18998b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif /* !IA64 */
19006d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* SPARC || SPARC64 */
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC	/* This code is slightly sparc specific */
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1906e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define BPT	0x91d02001	/* ta	1 */
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOP	0x10800000	/* ba	0 */
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define LOOPA	0x30800000	/* ba,a	0 */
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define NOP	0x01000000
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if LOOPA
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *)tcp->inst) < 0) {
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanclearbpt(tcp)
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
19610e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#if defined(I386) || defined(X86_64)
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
1963faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(POWERPC)
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1965faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1967faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
1969c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
1970c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long iaoq;
1971ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
1972ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman       long pc;
1973faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* architecture */
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19756d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#if defined (SPARC) || defined (SPARC64)
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Again, we borrow the SunOS breakpoint code. */
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if(errno) {
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
1988faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(IA64)
19897b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	if (ia32) {
19907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		unsigned long addr;
19917b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
19927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (debug)
19937b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
19947b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (!(tcp->flags & TCB_BPTSET)) {
19957b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
19967b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
19977b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
19987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		errno = 0;
19997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
20007b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (errno) {
20017b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
20027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
20037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
20047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
20057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2006932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IIP, &addr) < 0)
20077b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return -1;
20087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		if (addr != tcp->baddr) {
20097b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			/* The breakpoint has not been reached yet.  */
20107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			if (debug)
20117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				fprintf(stderr,
20127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
20137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman						addr, tcp->baddr);
20147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman			return 0;
20157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman		}
20167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman	} else {
20178b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		unsigned long addr, ipsr;
20188b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid_t pid;
20198b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
20208b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		pid = tcp->pid;
20218b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
2022932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
20238b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
2024932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, PT_CR_IIP, &addr) < 0)
20258b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
20268b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
20278b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original bundle: */
20288b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
20298b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
20308b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
20318b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
20328b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
20338b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
20348b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
20358b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
20368b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		/* restore original "ri" in ipsr: */
20378b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
20388b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		errno = 0;
20398b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
20408b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (errno) {
20418b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
20428b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return -1;
20438b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
20448b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
20458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		tcp->flags &= ~TCB_BPTSET;
20468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
20478b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		if (addr != (tcp->baddr & ~0x3)) {
20488b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			/* the breakpoint has not been reached yet.  */
20498b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			if (debug)
20508b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman				fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
20518b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman					addr, tcp->baddr);
20528b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			return 0;
20538b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		}
20548b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
20556d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#else /* !IA64  && !SPARC && !SPARC64 */
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug)
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	errno = 0;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno) {
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef I386
2072932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &eip) < 0)
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (eip != tcp->baddr) {
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					eip, tcp->baddr);
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
20820e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig#elif defined(X86_64)
2083932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &eip) < 0)
20840e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return -1;
20850e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	if (eip != tcp->baddr) {
20860e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		/* The breakpoint has not been reached yet.  */
20870e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		if (debug)
20880e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig			fprintf(stderr,
20890e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
20900e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig					eip, tcp->baddr);
20910e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return 0;
20920e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
2093c792698a99b640e7d256e8692c992bd967f0c5b2Wichert Akkerman#elif defined(POWERPC)
2094932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2103faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(M68K)
2104932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0)
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2113faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(ALPHA)
2114932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0)
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pc != tcp->baddr) {
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet.  */
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pc, tcp->baddr);
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2123c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman#elif defined(HPPA)
2124932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
2125c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return -1;
2126c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq &= ~0x03;
2127c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2128c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		/* The breakpoint has not been reached yet.  */
2129c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		if (debug)
2130c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman			fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2131c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman				iaoq, tcp->baddr);
2132c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return 0;
2133c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
2134c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	iaoq = tcp->baddr | 3;
2135c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	/* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2136c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2137c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 * has no significant effect.
2138c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	 */
2139c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2140c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
2141ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman#elif defined(SH)
2142932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko       if (upeek(tcp, 4*REG_PC, &pc) < 0)
2143ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman               return -1;
2144ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        if (pc != tcp->baddr) {
2145ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                /* The breakpoint has not been reached yet.  */
2146ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                if (debug)
2147ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                        fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2148ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                                pc, tcp->baddr);
2149ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman                return 0;
2150ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman        }
2151ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
2152faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#endif /* arch */
21536d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath#endif /* !SPARC && !SPARC64 && !IA64 */
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SPARC
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
2160e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if !LOOPA
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * to adjust the program counter after removing the our `breakpoint'.
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((regs.r_pc < tcp->baddr) ||
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(regs.r_pc > tcp->baddr + 4)) {
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					regs.r_pc, tcp->parent->baddr);
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LOOPA */
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SPARC */
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2209d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath#endif
2210d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
2211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
2216932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkogetex(tcp, hdr)
2217932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkostruct tcb *tcp;
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct exec *hdr;
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
2224932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfixvfork(tcp)
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2252932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (getex(tcp, &hdr) < 0)
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
226646100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[symbol: %s]\n", cp);
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
2307