util.c revision 4924dbd6d750665cf383b20ab4fd67e48219ab91
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
818566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#if defined(LINUXSPARC) && defined (SPARC64)
826d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# undef PTRACE_GETREGS
836d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# define PTRACE_GETREGS PTRACE_GETREGS64
846d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# undef PTRACE_SETREGS
856d1a65c759c6c650e47ce5045a26380a4acbdffaRoland McGrath# define PTRACE_SETREGS PTRACE_SETREGS64
869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* macros */
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MAX
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define MAX(a,b)		(((a) > (b)) ? (a) : (b))
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MIN
9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define MIN(a,b)		(((a) < (b)) ? (a) : (b))
9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
971201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_nz(struct timeval *a)
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return a->tv_sec || a->tv_usec;
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1031201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_cmp(struct timeval *a, struct timeval *b)
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec < b->tv_sec
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec > b->tv_sec
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandouble
1151201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_float(struct timeval *tv)
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return tv->tv_sec + tv->tv_usec/1000000.0;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1211201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec + b->tv_sec;
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec + b->tv_usec;
12558372f52ac5f824be687c01bfc1db1ffb963f91eRoland McGrath	if (tv->tv_usec >= 1000000) {
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec++;
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec -= 1000000;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1321201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec - b->tv_sec;
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec - b->tv_usec;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (((long) tv->tv_usec) < 0) {
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec--;
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec += 1000000;
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1431201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_div(struct timeval *tv, struct timeval *a, int n)
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1511201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_mul(struct timeval *tv, struct timeval *a, int n)
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec * n;
154fefdd97156bb2f86c5b6596dc7e28d954516b3edDmitry V. Levin	tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinconst char *
159ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinxlookup(const struct xlat *xlat, int val)
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (; xlat->str != NULL; xlat++)
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val == val)
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return xlat->str;
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
168eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Generic ptrace wrapper which tracks ESRCH errors
169eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * by setting tcp->ptrace_errno to ESRCH.
170732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko *
171732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * We assume that ESRCH indicates likely process death (SIGKILL?),
172732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * modulo bugs where process somehow ended up not stopped.
173732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Unfortunately kernel uses ESRCH for that case too. Oh well.
174eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath *
175eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Currently used by upeek() only.
176eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * TODO: use this in all other ptrace() calls while decoding.
177732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
178732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkolong
179eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathdo_ptrace(int request, struct tcb *tcp, void *addr, void *data)
180732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
181732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	long l;
182732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
183732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
18409a13c2da736aa9a74e7de761062c82832f7cf04Mike Frysinger	l = ptrace(request, tcp->pid, addr, (long) data);
185eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	/* Non-ESRCH errors might be our invalid reg/mem accesses,
186eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	 * we do not record them. */
187eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (errno == ESRCH)
188eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		tcp->ptrace_errno = ESRCH;
189732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return l;
190732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
191732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
192732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
193732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Used when we want to unblock stopped traced process.
194732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
195732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Returns 0 on success or if error was ESRCH
196732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * (presumably process was killed while we talk to it).
197732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Otherwise prints error message and returns -1.
198732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
199732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkoint
200eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathptrace_restart(int op, struct tcb *tcp, int sig)
201732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
202732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	int err;
203eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	const char *msg;
204732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
205732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
20609a13c2da736aa9a74e7de761062c82832f7cf04Mike Frysinger	ptrace(op, tcp->pid, (void *) 1, (long) sig);
207732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	err = errno;
208732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (!err || err == ESRCH)
209732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		return 0;
210732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
211732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	tcp->ptrace_errno = err;
212eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	msg = "SYSCALL";
213eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (op == PTRACE_CONT)
214eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		msg = "CONT";
215eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (op == PTRACE_DETACH)
216eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		msg = "DETACH";
217eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
218eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			msg, sig, strerror(err));
219732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return -1;
220732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
221732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
222732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
226ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
228ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", str);
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
236b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#if HAVE_LONG_LONG
237b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab/*
238b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * Print 64bit argument at position llarg and return the index of the next
239b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * argument.
240b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab */
241b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabint
242b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabprintllval(struct tcb *tcp, const char *format, int llarg)
243b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab{
244b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# if defined(FREEBSD) \
245d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab     || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
2467a5b08fb26dcfb343e2c89567bf139af252a95fdDmitry V. Levin     || defined(LINUX_MIPSO32) \
2477a5b08fb26dcfb343e2c89567bf139af252a95fdDmitry V. Levin     || defined(__ARM_EABI__)
248b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	/* Align 64bit argument to 64bit boundary.  */
2494b08df42ff069dcf44b8ed206ae33a2904c366baDenys Vlasenko	llarg = (llarg + 1) & 0x1e;
250b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# endif
251d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab# if defined LINUX && (defined X86_64 || defined POWERPC64)
252b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	if (current_personality == 0) {
253b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, tcp->u_arg[llarg]);
254b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg++;
255b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	} else {
256d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  ifdef POWERPC64
257d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab		/* Align 64bit argument to 64bit boundary.  */
2584b08df42ff069dcf44b8ed206ae33a2904c366baDenys Vlasenko		llarg = (llarg + 1) & 0x1e;
259d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  endif
260b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
261b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg += 2;
262b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	}
263d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab# elif defined IA64 || defined ALPHA
264b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->u_arg[llarg]);
265b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
266b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# elif defined LINUX_MIPSN32
267b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->ext_arg[llarg]);
268b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
269b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# else
270b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
271b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg += 2;
272b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# endif
273b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	return llarg;
274b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab}
275b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#endif
276b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
2824924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenkovoid
2831201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoaddflags(const struct xlat *xlat, int flags)
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2854924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko	for (; xlat->str; xlat++) {
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
296a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
2974924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko * Interpret `xlat' as an array of flags.
298a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
299a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
300a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
301a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
302a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
303a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
304a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
305a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
306a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
307a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	strcpy(outstr, prefix);
308a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
309a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
310a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
311a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
312a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath				strcat(outstr, "|");
313a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, xlat->str);
314a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			flags &= ~xlat->val;
315a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
316a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
317a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
318a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
319a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
320a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, "|");
321a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		sprintf(outstr + strlen(outstr), "%#x", flags);
322a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
323a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
324a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
325a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
326a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
32830145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintflags(const struct xlat *xlat, int flags, const char *dflt)
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
33130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin	const char *sep;
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
347b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
348b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
349b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
350b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
351b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
352b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
353b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
354b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
355b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
356b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
357b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
358b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
359b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
360b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
361b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
36276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
363b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
36830145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum(struct tcb *tcp, long addr, const char *fmt)
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
370eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
37376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3856bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
38630145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum_int(struct tcb *tcp, long addr, const char *fmt)
3879814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3889814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3899814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3909814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
3919814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
3929814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3939814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3949814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
3959814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
3969814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3979814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3989814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
3999814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
4009814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
4019814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
4029814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4039814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4043138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinprintfd(struct tcb *tcp, int fd)
4053138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin{
4068a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	const char *p;
4078a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
4088a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	if (show_fd_path && (p = getfdpath(tcp, fd)))
4098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d<%s>", fd, p);
4108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	else
4118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d", fd);
4123138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin}
4133138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin
4143138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinvoid
4151201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintuid(const char *text, unsigned long uid)
4166bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4176bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
4186bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
4196bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4206bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
423a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
424a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
425a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
426a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat `instr' as a NUL-terminated string
427a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
428a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
4296d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrathstatic int
430bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinstring_quote(const char *instr, char *outstr, int len, int size)
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
432bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
433bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
434bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	int usehex = 0, c, i;
43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
436bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
437bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
438bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
439a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
440a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
441bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
442bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
443a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
444a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
445a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
446a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
447a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
448a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
449a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
450a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
451bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
452bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
453bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
454bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
455bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
45676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
457bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
458bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
459bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
460bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
461a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
462bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
463bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
464a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
465a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
466a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
467a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
468a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
469a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
470a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
471a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
472bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			sprintf(s, "\\x%02x", c);
473bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			s += 4;
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
475bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
476bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
477bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
478a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
479a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
480a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
481a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
482a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
483a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
484a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
485a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
486bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
487bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
488bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
489bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
490bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
491bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
492bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
493bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
494bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
495bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
496bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
497bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
498bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
500bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
502bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
503bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
505bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
509bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
510bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
511bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
512bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
513bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					else if (i + 1 < size
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						 && isdigit(ustr[i + 1])) {
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%03o", c);
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += 4;
518bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					} else {
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%o", c);
520bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += strlen(s);
521bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
522bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
523bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
527bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
528bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
5296d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
5306d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	/* Return nonzero if the string was unterminated.  */
5316d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	return i == size;
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
534a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
535a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
536a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
537a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
539bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
541a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
542371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
543bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
544bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
545bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
546a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Cap path length to the path buffer size,
547a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	   and NUL-terminate the buffer. */
548a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
549a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
550bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	path[n] = '\0';
551a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
552a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
553bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (umovestr(tcp, addr, n + 1, path) < 0)
55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
556bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
557bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		int trunc = (path[n] != '\0');
558bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
559bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (trunc)
560bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			path[n] = '\0';
561a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		(void) string_quote(path, outstr, -1, n + 1);
562a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		if (trunc)
563bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			strcat(outstr, "...");
564bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		tprintf("%s", outstr);
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
569bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
570bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
571bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	printpathn(tcp, addr, sizeof path - 1);
572bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
573bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
574a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
575a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
576a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
577a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
578a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
579bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
580bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintstr(struct tcb *tcp, long addr, int len)
58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
582bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
58376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
5846d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
58776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
58976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
590a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
591a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str)
592a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
593a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!outstr)
594a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		outstr = malloc(4 * max_strlen + sizeof "\"...\"");
595a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str || !outstr) {
596a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		fprintf(stderr, "out of memory\n");
597a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		tprintf("%#lx", addr);
598a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		return;
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
600bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
602a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
603a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
604a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
605a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
606bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
607a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str[max_strlen] = '\0';
608bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
61376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
614a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		size = MIN(len, max_strlen);
615bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
621a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (string_quote(str, outstr, len, size) &&
622a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	    (len < 0 || len > max_strlen))
623bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		strcat(outstr, "...");
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6281d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6291d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6301201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpiov(struct tcb *tcp, int len, long addr)
6311d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6324ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
6334ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6344ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6354ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6364ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6374ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6384ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6394ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6404ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6414ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6424ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6434ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6444ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6454ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6464ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6474ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6481d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6494ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6504ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6514ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6524ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6531d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
654aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
6551d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
6564ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
6574ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
6584ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
659aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
6601d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
6611d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
662aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
6631d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
664adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			/* include the buffer number to make it easy to
665adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			 * match up the trace with the source */
666adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			tprintf(" * %lu bytes in buffer %d\n",
667adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				(unsigned long)iov_iov_len(i), i);
668adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			dumpstr(tcp, (long) iov_iov_base(i),
669adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				iov_iov_len(i));
670adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		}
6711d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
6721d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
6734ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6744ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6754ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6764ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6771d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6781d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
6811201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpstr(struct tcb *tcp, long addr, int len)
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
69346100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
740ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumoven(struct tcb *tcp, long addr, int len, char *laddr)
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
743eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
7455daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
755eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
756eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
757eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
758eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
759eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
760eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
761eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
762eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* But if not started, we had a bogus address. */
763eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
764eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
765eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
766eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
7675daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
772eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
773eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
774eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
775eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
776eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
779eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
781eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
782eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
7835daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
796eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(PTRACE_READDATA, pid,
797eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			   (char *) addr, len, laddr) < 0) {
798eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (errno != ESRCH) {
799eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umoven: ptrace(PTRACE_READDATA, ...)");
800eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				abort();
801eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
810bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
811ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
812aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
8139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
814aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
816aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
817aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
819bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
829ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumovestr(struct tcb *tcp, long addr, int len, char *laddr)
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
831bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
832aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
833aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
834aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
835aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
836aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
837aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
838aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
839aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
840aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
841aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
842aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
843aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
844b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	int page = 1024;	/* How to find this? */
845aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
846aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
847aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
848aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
849aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
850aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
851aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
8529cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
853aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
854b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (memchr(laddr, 0, move)) break;
855aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
856aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
857aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
858aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
859aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
860bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
8615daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
862eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
873eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
874eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
875eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
876eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
877eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
878eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
879eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
880eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
881eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
882eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
883eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
8845daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
885b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n, len));
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
892eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
893eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
894eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
895eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
896eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
897eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
898eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
899eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
900eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
901eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
902eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9035daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
911bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
912aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
9163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# if !defined (SPARC) && !defined(SPARC64)
9173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITETEXT	101
9183bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITEDATA	102
9193bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !SPARC && !SPARC64 */
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
9251201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkouload(int cmd, int pid, long addr, int len, char *laddr)
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
946eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
947eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(peek, pid, (char *) addr, 0);
948eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
949eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
951eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
952eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
953eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
954eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
957eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
961eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			u.val = ptrace(peek, pid, (char *) addr, 0);
962eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
963eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
964eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
967eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
972eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
9731201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotload(int pid, int addr, int len, char *laddr)
974eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath{
975eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
976eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath}
977eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
978eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
9791201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodload(int pid, int addr, int len, char *laddr)
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
981eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
986bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
9891201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoupeek(struct tcb *tcp, long off, long *res)
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1006d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
10153bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1016eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1017732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1018eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (val == -1 && errno) {
1019eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno != ESRCH) {
1020eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			char buf[60];
1021b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1022eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror(buf);
1023eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1025eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	}
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1030bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1033ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenkoprintcall(struct tcb *tcp)
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10357a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
10367a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
10377a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
10403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef I386
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1043932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &eip) < 0) {
10447a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1048eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(S390) || defined(S390X)
1050adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long psw;
1051b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
1052adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		PRINTBADPC;
1053adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1054adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
10553bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef S390
1056adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", psw);
10573bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif S390X
1058adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%16lx] ", psw);
10593bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1060eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10613bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(X86_64)
10620e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
10630e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
1064932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &rip) < 0) {
10657a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
10660e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
10670e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
10680e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
10693bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(IA64)
10708b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
10718b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
1072932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_B0, &ip) < 0) {
10737a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
10748b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
10758b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
10768b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
10773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(POWERPC)
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1080932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1081d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab		PRINTBADPC;
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1084d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  ifdef POWERPC64
1085d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab	tprintf("[%016lx] ", pc);
1086d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  else
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
1088d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  endif
10893bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(M68K)
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1092932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1093b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
10973bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ALPHA)
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1100932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
1101b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????????????] ");
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11053bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SPARC) || defined(SPARC64)
11068566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	struct pt_regs regs;
1107b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
11087a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11118566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  if defined(SPARC64)
11128566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.tpc);
11138566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  else
11148566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.pc);
11158566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  endif
11163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(HPPA)
1117c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1118c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1119b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1120b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
1121c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1122c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1123c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
11243bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(MIPS)
112575c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
112675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
1127932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_EPC, &pc) < 0) {
1128b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
112975c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
113075c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
113175c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
11323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH)
1133adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long pc;
1134ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1135adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1136b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
1137adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1138adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
1139adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", pc);
11403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH64)
1141e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1142e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1143932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
1144b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????????????] ");
1145e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1146e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1147e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
11483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ARM)
1149ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1150e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1151932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*15, &pc) < 0) {
11527a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1153ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1154ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1155ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
11565ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko# elif defined(AVR32)
11575ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	long pc;
11585ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko
11595ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
11605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		tprintf("[????????] ");
11615ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return;
11625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	}
11635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	tprintf("[%08lx] ", pc);
11643bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(BFIN)
116587ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	long pc;
116687ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin
1167932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_PC, &pc) < 0) {
116887ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		PRINTBADPC;
116987ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return;
117087ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	}
117187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	tprintf("[%08lx] ", pc);
1172ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV10)
1173ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1174ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1175eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1176ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1177ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1178ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1179ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
1180ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV32)
1181ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1182ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1183eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1184ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1185ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1186ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1187ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
11883bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* architecture */
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1194eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1195eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
11967a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
12047a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12143bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
12153bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko/*
12163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * These #if's are huge, please indent them correctly.
12173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * It's easy to get confused otherwise.
12183bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko */
1219bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1221e7c9024acf94101ceb17006102629f14e0f25553Denys Vlasenko# ifdef LINUX
1222d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12233bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include "syscall.h"
12243291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
12253bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include <sys/syscall.h>
12263bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_PTRACE
12273bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_PTRACE    0x00002000
12283bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12293bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VFORK
12303bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VFORK     0x00004000
12313bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VM
12333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VM        0x00000100
12343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12353bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_STOPPED
12363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_STOPPED   0x02000000
12373bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1238d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12393bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef IA64
1240d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
124108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
124208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
12433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_fork	2
12443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_vfork	190
124508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1246d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1247d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1248d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1249d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1250d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
12511f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
12521f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1253d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12541f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
12551f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
12561f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
125708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
12581f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
125908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1260932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1261d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1262932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1263d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1264d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1265d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1266d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
12671f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1268d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12691f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1270d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1271d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1272d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12733bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
1274d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12753bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SYS_fork
1276d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12771201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1278d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
127908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
128008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
128108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1282b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R11, valp);
128308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1284b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
128508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
128608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
128708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1288d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1289d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1290d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12911201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1292d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
129308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
129408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
129508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1296b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R9, valp);
129708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1298b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
129908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
130008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
130108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1302d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
13033bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1304d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1305d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13061201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1307d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
130808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
130908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
131008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
131108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
131208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
131308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
131408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
131508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1316eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1317eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1318eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1319d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1320d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1321d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13221201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1323d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
132408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
132508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
132608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
132708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
132808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
132908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
133008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
133108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1332eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1333eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1334eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1335d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1336d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1337b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1338b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1339b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) ((void) (state), 0)
13413bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) ((void) (state), 0)
1342b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif defined (SPARC) || defined (SPARC64)
1344d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13458566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysingertypedef struct pt_regs arg_setup_state;
1346d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13473bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) \
1348b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
13493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state) \
1350b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1351d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13528566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
13538566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
13548566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
13558566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
13563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) 0
1357d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13583bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  else /* other architectures */
1359d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   if defined S390 || defined S390X
13617b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
13627b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
13637b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
13647b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
13653bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	PT_GPR3
13663bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	PT_ORIGGPR2
13673bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
13683bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg1(tcp, state, val) ((void) (state), 0)
13693bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_index	1
13703bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_index	0
13713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (ALPHA) || defined (MIPS)
13723bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	REG_A0
13733bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(REG_A0+1)
13745ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#   elif defined (AVR32)
13755ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg0_offset	(REG_R12)
13765ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg1_offset	(REG_R11)
13773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (POWERPC)
13783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(sizeof(unsigned long)*PT_R3)
13793bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(sizeof(unsigned long)*PT_R4)
13803bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
13813bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (HPPA)
13823bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	 PT_GR26
13833bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	 (PT_GR26-4)
13843bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (X86_64)
13853bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
13863bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
13873bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH)
13883bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(4*(REG_REG0+4))
13893bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(4*(REG_REG0+5))
13903bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH64)
13913bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko    /* ABI defines arg0 & 1 in r2 & r3 */
13923bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset   (REG_OFFSET+16)
13933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset   (REG_OFFSET+24)
13943bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) 0
1395ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#   elif defined CRISV10 || defined CRISV32
1396ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_offset   (4*PT_R11)
1397ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_offset   (4*PT_ORIG_R10)
1398ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg0(tcp, state, val) 0
1399ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg1(tcp, state, val) 0
1400ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_index   1
1401ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_index   0
14023bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   else
14033bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	0
14043bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	4
14053bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if defined ARM
14063bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#     define restore_arg0(tcp, state, val) 0
14073bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
14083bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1409d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1410d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1411d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14123bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) (0)
14133bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
14143bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg0(tcp, cookie, valp) \
1415b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (upeek((tcp), arg0_offset, (valp)))
14163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg1(tcp, cookie, valp) \
1417b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (upeek((tcp), arg1_offset, (valp)))
1418d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1419d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
14201201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, void *cookie, long val)
1421d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1422b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1423d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1424d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1425d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
14261201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, void *cookie, long val)
1427d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1428b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1429d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1430d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14313bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* architectures */
1432d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg0
14343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
14353bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg1
14373bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
14383bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1439d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef arg0_index
14413bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg0_index 0
14423bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg1_index 1
14433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
144490d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1445d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1446418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkosetbpt(struct tcb *tcp)
1447d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
14483291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1449d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1450d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1451d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1452d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1453d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1454d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1455d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14563291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
14573291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
14583291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
14593291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
14603291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
14613291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
14623291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
14633291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
14643291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
14653291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
14663291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
14673291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
14683291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
14693291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
147076989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
14713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_vfork
14729383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
14733bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14743bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_fork
1475d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
14763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  if defined SYS_fork || defined SYS_vfork
1478b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (arg_setup(tcp, &state) < 0
1479b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1480b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg1(tcp, &state, &tcp->inst[1]) < 0
14813291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		    || change_syscall(tcp, clone_scno[current_personality]) < 0
1482b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1483b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg1(tcp, &state, 0) < 0
1484b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || arg_finish_change(tcp, &state) < 0)
1485d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1486c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1487c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1488d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1489d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
14903bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1491d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1492c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko	case SYS_clone: ;
14933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_clone2
1494c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko	case SYS_clone2: ;
14953bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14968fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
14978fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   contrary to x86 SYS_vfork above.  Even on x86 we turn the
14988fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
14998fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
15008fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
15018fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
15028fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
15038fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1504c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1505c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (new_arg0 & CLONE_VFORK)
1506c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1507c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (arg_setup(tcp, &state) < 0
1508c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || set_arg0(tcp, &state, new_arg0) < 0
1509c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || arg_finish_change(tcp, &state) < 0)
15105ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			return -1;
1511d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1512c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1513c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1514d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1515d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1516d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1517d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1518d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1519d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1520d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1521d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1522d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1523d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1524d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1525d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
15261201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
1527d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1528d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1529b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (arg_setup(tcp, &state) < 0
1530b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1531b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1532b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || arg_finish_change(tcp, &state))
1533c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (errno != ESRCH)
1534c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			return -1;
1535d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1536d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1537d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1538d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
15393bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# else /* !defined LINUX */
1540d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
15421201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkosetbpt(struct tcb *tcp)
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
15453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC	/* This code is slightly sparc specific */
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1547e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
15483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define BPT	0x91d02001	/* ta	1 */
15493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOP	0x10800000	/* ba	0 */
15503bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOPA	0x30800000	/* ba,a	0 */
15513bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define NOP	0x01000000
15523bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if LOOPA
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
15543bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    else
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
15563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1562eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1563eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
1567eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1568eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				sizeof tcp->inst, (char *)tcp->inst) < 0) {
1569eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1583eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
1585eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15903bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
15913bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
15971201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15993bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
16003bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16023bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
1603e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
16043bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1610eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
1612eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
16203bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko	 * to adjust the program counter after removing our `breakpoint'.
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1622eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1623eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1626eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if ((regs.r_pc < tcp->baddr) ||
1627eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				(regs.r_pc > tcp->baddr + 4)) {
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
16323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko					regs.r_pc, tcp->baddr);
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
1641eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1642eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif /* LOOPA */
16463bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
16473bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16523bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !defined LINUX */
1653d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1654bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16601201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkogetex(struct tcb *tcp, struct exec *hdr)
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
1666932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
16801201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkofixvfork(struct tcb *tcp)
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1693932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (getex(tcp, &hdr) < 0)
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
170746100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1710eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
1728eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
1741