util.c revision b63256e69bf3f1a74aadb0e14556490bc8f4ef95
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.  */
249b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	if (llarg % 2) llarg++;
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.  */
258d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab		if (llarg % 2) llarg++;
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 */
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
2831201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoaddflags(const struct xlat *xlat, int flags)
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n++;
29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
301a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
302a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Interpret `xlat' as an array of flags/
303a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
304a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
305a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
306a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
307a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
308a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
309a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
310a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
311a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
312a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	strcpy(outstr, prefix);
313a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
314a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
315a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
316a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
317a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath				strcat(outstr, "|");
318a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, xlat->str);
319a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			flags &= ~xlat->val;
320a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
321a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
322a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
323a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
324a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
325a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, "|");
326a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		sprintf(outstr + strlen(outstr), "%#x", flags);
327a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
328a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
329a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
330a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
331a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
33330145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintflags(const struct xlat *xlat, int flags, const char *dflt)
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
33630145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin	const char *sep;
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
34776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
34876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
35176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
352b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
353b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
354b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
355b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
356b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
357b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
358b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
359b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
360b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
361b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
362b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
363b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
364b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
365b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
366b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
368b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
37330145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum(struct tcb *tcp, long addr, const char *fmt)
37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
375eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3906bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
39130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum_int(struct tcb *tcp, long addr, const char *fmt)
3929814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3939814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3949814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3959814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
3969814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
3979814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3989814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3999814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
4009814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
4019814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4029814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
4039814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
4049814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
4059814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
4069814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
4079814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4089814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4093138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinprintfd(struct tcb *tcp, int fd)
4103138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin{
4118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	const char *p;
4128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
4138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	if (show_fd_path && (p = getfdpath(tcp, fd)))
4148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d<%s>", fd, p);
4158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	else
4168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d", fd);
4173138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin}
4183138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin
4193138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinvoid
4201201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintuid(const char *text, unsigned long uid)
4216bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4226bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
4236bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
4246bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4256bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
428a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
429a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
430a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
431a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat `instr' as a NUL-terminated string
432a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
433a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
4346d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrathstatic int
435bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinstring_quote(const char *instr, char *outstr, int len, int size)
43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
437bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
438bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
439bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	int usehex = 0, c, i;
44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
441bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
442bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
443bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
444a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
445a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
446bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
447bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
448a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
449a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
450a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
451a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
452a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
453a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
454a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
455a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
456bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
457bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
458bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
459bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
460bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
462bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
463bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
464bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
465bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
466a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
467bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
468bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
469a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
470a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
471a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
472a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
473a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
474a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
475a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
476a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
477bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			sprintf(s, "\\x%02x", c);
478bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			s += 4;
479bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
480bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
481bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
482bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
483a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
484a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
485a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
486a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
487a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
488a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
489a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
490a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
491bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
492bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
493bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
494bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
495bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
496bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
497bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
498bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
500bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
502bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
503bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
505bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
509bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
510bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
511bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
512bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
513bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
518bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					else if (i + 1 < size
520bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						 && isdigit(ustr[i + 1])) {
521bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%03o", c);
522bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += 4;
523bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					} else {
524bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%o", c);
525bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += strlen(s);
526bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
527bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
528bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
532bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
533bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
5346d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
5356d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	/* Return nonzero if the string was unterminated.  */
5366d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	return i == size;
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
539a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
540a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
541a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
542a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
544bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
546a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
547371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
548bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
549bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
550bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
551a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Cap path length to the path buffer size,
552a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	   and NUL-terminate the buffer. */
553a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
554a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
555bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	path[n] = '\0';
556a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
557a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
558bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (umovestr(tcp, addr, n + 1, path) < 0)
55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
56076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
561bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
562bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		int trunc = (path[n] != '\0');
563bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
564bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (trunc)
565bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			path[n] = '\0';
566a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		(void) string_quote(path, outstr, -1, n + 1);
567a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		if (trunc)
568bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			strcat(outstr, "...");
569bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		tprintf("%s", outstr);
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
574bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
575bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
576bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	printpathn(tcp, addr, sizeof path - 1);
577bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
578bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
579a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
580a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
581a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
582a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
583a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
584bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
585bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintstr(struct tcb *tcp, long addr, int len)
58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
587bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
5896d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
59076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
59276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
59376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
595a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
596a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str)
597a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
598a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!outstr)
599a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		outstr = malloc(4 * max_strlen + sizeof "\"...\"");
600a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str || !outstr) {
601a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		fprintf(stderr, "out of memory\n");
602a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		tprintf("%#lx", addr);
603a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		return;
60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
605bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
607a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
608a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
609a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
610a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
611bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
612a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str[max_strlen] = '\0';
613bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
619a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		size = MIN(len, max_strlen);
620bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
626a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (string_quote(str, outstr, len, size) &&
627a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	    (len < 0 || len > max_strlen))
628bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		strcat(outstr, "...");
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6331d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6341d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6351201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpiov(struct tcb *tcp, int len, long addr)
6361d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6374ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
6384ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6394ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6404ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6414ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6424ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6434ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6444ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6454ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6464ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6474ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6484ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6494ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6504ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6514ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6524ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6531d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6544ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6554ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6564ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6574ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6581d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
659aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
6601d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
6614ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
6624ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
6634ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
664aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
6651d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
6661d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
667aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
6681d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
669adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			/* include the buffer number to make it easy to
670adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			 * match up the trace with the source */
671adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			tprintf(" * %lu bytes in buffer %d\n",
672adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				(unsigned long)iov_iov_len(i), i);
673adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			dumpstr(tcp, (long) iov_iov_base(i),
674adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				iov_iov_len(i));
675adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		}
6761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
6771d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
6784ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6794ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6804ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6814ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6821d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6831d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6841d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
6861201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpstr(struct tcb *tcp, long addr, int len)
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
69846100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
745ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumoven(struct tcb *tcp, long addr, int len, char *laddr)
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
748eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
7505daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
760eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
761eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
762eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
763eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
764eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
765eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
766eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
767eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* But if not started, we had a bogus address. */
768eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
769eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
770eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
771eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
7725daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
779eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
781eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
782eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
783eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
784eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
785eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
786eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
787eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
7885daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
801eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(PTRACE_READDATA, pid,
802eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			   (char *) addr, len, laddr) < 0) {
803eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (errno != ESRCH) {
804eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umoven: ptrace(PTRACE_READDATA, ...)");
805eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				abort();
806eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
815bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
816ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
817aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
8189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
819aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
821aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
822aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
824bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
834ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumovestr(struct tcb *tcp, long addr, int len, char *laddr)
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
837aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
838aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
839aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
840aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
841aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
842aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
843aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
844aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
845aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
846aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
847aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
848aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
849b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	int page = 1024;	/* How to find this? */
850aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
851aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
852aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
853aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
854aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
855aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
856aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
8579cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
858aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
859b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (memchr(laddr, 0, move)) break;
860aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
861aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
862aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
863aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
864aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
865bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
8665daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
867eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
878eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
879eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
880eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
881eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
882eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
883eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
884eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
885eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
886eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
887eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
888eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
8895daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
890b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n, len));
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
897eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
898eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
899eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
900eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
901eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
902eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
903eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
904eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
905eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
906eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
907eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9085daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
916bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
917aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
9213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# if !defined (SPARC) && !defined(SPARC64)
9223bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITETEXT	101
9233bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITEDATA	102
9243bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !SPARC && !SPARC64 */
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
9301201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkouload(int cmd, int pid, long addr, int len, char *laddr)
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
951eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
952eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(peek, pid, (char *) addr, 0);
953eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
954eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
956eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
957eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
958eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
959eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
962eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
966eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			u.val = ptrace(peek, pid, (char *) addr, 0);
967eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
968eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
969eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
972eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
977eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
9781201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotload(int pid, int addr, int len, char *laddr)
979eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath{
980eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
981eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath}
982eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
983eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
9841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodload(int pid, int addr, int len, char *laddr)
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
986eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
991bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
9941201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoupeek(struct tcb *tcp, long off, long *res)
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9983bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1011d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
10203bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1021eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1022732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1023eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (val == -1 && errno) {
1024eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno != ESRCH) {
1025eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			char buf[60];
1026b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1027eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror(buf);
1028eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1030eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	}
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1035bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1038ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenkoprintcall(struct tcb *tcp)
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10407a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
10417a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
10427a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
10453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef I386
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1048932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &eip) < 0) {
10497a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1053eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10543bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(S390) || defined(S390X)
1055adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long psw;
1056b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
1057adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		PRINTBADPC;
1058adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1059adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
10603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef S390
1061adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", psw);
10623bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif S390X
1063adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%16lx] ", psw);
10643bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1065eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10663bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(X86_64)
10670e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
10680e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
1069932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &rip) < 0) {
10707a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
10710e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
10720e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
10730e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
10743bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(IA64)
10758b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
10768b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
1077932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_B0, &ip) < 0) {
10787a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
10798b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
10808b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
10818b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
10823bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(POWERPC)
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1085932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1086d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab		PRINTBADPC;
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1089d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  ifdef POWERPC64
1090d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab	tprintf("[%016lx] ", pc);
1091d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  else
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
1093d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  endif
10943bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(M68K)
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1097932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1098b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11023bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ALPHA)
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1105932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
1106b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????????????] ");
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11103bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SPARC) || defined(SPARC64)
11118566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	struct pt_regs regs;
1112b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
11137a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11168566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  if defined(SPARC64)
11178566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.tpc);
11188566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  else
11198566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.pc);
11208566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  endif
11213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(HPPA)
1122c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1123c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1124b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1125b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
1126c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1127c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1128c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
11293bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(MIPS)
113075c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
113175c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
1132932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_EPC, &pc) < 0) {
1133b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
113475c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
113575c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
113675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
11373bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH)
1138adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long pc;
1139ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1140adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1141b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????] ");
1142adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1143adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
1144adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", pc);
11453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH64)
1146e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1147e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1148932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
1149b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		tprintf("[????????????????] ");
1150e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1151e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1152e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
11533bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ARM)
1154ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1155e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1156932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*15, &pc) < 0) {
11577a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1158ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1159ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1160ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
11615ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko# elif defined(AVR32)
11625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	long pc;
11635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko
11645ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
11655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		tprintf("[????????] ");
11665ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return;
11675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	}
11685ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	tprintf("[%08lx] ", pc);
11693bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(BFIN)
117087ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	long pc;
117187ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin
1172932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_PC, &pc) < 0) {
117387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		PRINTBADPC;
117487ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return;
117587ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	}
117687ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	tprintf("[%08lx] ", pc);
1177ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV10)
1178ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1179ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1180eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1181ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1182ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1183ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1184ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
1185ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV32)
1186ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1187ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1188eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1189ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1190ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1191ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1192ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
11933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* architecture */
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1199eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1200eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
12017a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
12097a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1213bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1214bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1215bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1216bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12193bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
12203bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko/*
12213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * These #if's are huge, please indent them correctly.
12223bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * It's easy to get confused otherwise.
12233bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko */
1224bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1226e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levin#ifdef LINUX
1227d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12283bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include "syscall.h"
12293291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
12303bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include <sys/syscall.h>
12313bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_PTRACE
12323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_PTRACE    0x00002000
12333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VFORK
12353bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VFORK     0x00004000
12363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12373bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VM
12383bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VM        0x00000100
12393bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_STOPPED
12413bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_STOPPED   0x02000000
12423bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1243d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef IA64
1245d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
124608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
124708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
12483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_fork	2
12493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_vfork	190
125008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1251d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1252d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1253d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1254d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1255d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
12561f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
12571f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1258d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12591f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
12601f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
12611f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
126208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
12631f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
126408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1265932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1266d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1267932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1268d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1269d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1270d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1271d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
12721f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1273d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12741f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1275d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1276d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1277d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
1279d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12803bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SYS_fork
1281d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12821201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1283d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
128408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
128508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
128608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1287b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R11, valp);
128808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1289b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
129008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
129108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
129208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1293d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1294d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1295d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12961201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1297d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
129808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
129908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
130008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1301b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R9, valp);
130208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1303b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
130408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
130508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
130608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1307d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
13083bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1309d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1310d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1312d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
131308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
131408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
131508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
131608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
131708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
131808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
131908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
132008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1323eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1324d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1325d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1326d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13271201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1328d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
132908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
133008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
133108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
133208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
133308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
133408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
133508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
133608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1337eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1338eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1339eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1340d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1341d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1342b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1343b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1344b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) ((void) (state), 0)
13463bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) ((void) (state), 0)
1347b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif defined (SPARC) || defined (SPARC64)
1349d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13508566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysingertypedef struct pt_regs arg_setup_state;
1351d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13523bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) \
1353b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
13543bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state) \
1355b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1356d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13578566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
13588566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
13598566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
13608566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
13613bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) 0
1362d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13633bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  else /* other architectures */
1364d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13653bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   if defined S390 || defined S390X
13667b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
13677b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
13687b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
13697b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
13703bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	PT_GPR3
13713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	PT_ORIGGPR2
13723bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
13733bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg1(tcp, state, val) ((void) (state), 0)
13743bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_index	1
13753bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_index	0
13763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (ALPHA) || defined (MIPS)
13773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	REG_A0
13783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(REG_A0+1)
13795ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#   elif defined (AVR32)
13805ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg0_offset	(REG_R12)
13815ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg1_offset	(REG_R11)
13823bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (POWERPC)
13833bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(sizeof(unsigned long)*PT_R3)
13843bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(sizeof(unsigned long)*PT_R4)
13853bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
13863bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (HPPA)
13873bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	 PT_GR26
13883bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	 (PT_GR26-4)
13893bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (X86_64)
13903bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
13913bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
13923bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH)
13933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(4*(REG_REG0+4))
13943bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(4*(REG_REG0+5))
13953bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH64)
13963bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko    /* ABI defines arg0 & 1 in r2 & r3 */
13973bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset   (REG_OFFSET+16)
13983bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset   (REG_OFFSET+24)
13993bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) 0
1400ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#   elif defined CRISV10 || defined CRISV32
1401ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_offset   (4*PT_R11)
1402ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_offset   (4*PT_ORIG_R10)
1403ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg0(tcp, state, val) 0
1404ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg1(tcp, state, val) 0
1405ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_index   1
1406ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_index   0
14073bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   else
14083bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	0
14093bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	4
14103bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if defined ARM
14113bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#     define restore_arg0(tcp, state, val) 0
14123bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
14133bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1414d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1415d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1416d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) (0)
14183bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
14193bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg0(tcp, cookie, valp) \
1420b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (upeek((tcp), arg0_offset, (valp)))
14213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg1(tcp, cookie, valp) \
1422b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko    (upeek((tcp), arg1_offset, (valp)))
1423d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1424d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
14251201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, void *cookie, long val)
1426d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1427b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1428d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1429d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1430d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
14311201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, void *cookie, long val)
1432d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1433b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1434d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1435d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* architectures */
1437d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14383bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg0
14393bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
14403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14413bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg1
14423bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
14433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1444d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef arg0_index
14463bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg0_index 0
14473bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg1_index 1
14483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
144990d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1450d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1451418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkosetbpt(struct tcb *tcp)
1452d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
14533291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1454d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1455d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1456d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1457d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1458d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1459d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1460d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14613291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
14623291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
14633291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
14643291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
14653291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
14663291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
14673291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
14683291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
14693291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
14703291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
14713291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
14723291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
14733291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
14743291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
147576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
14763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_vfork
14779383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
14783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14793bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_fork
1480d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
14813bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14823bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  if defined SYS_fork || defined SYS_vfork
1483b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (arg_setup(tcp, &state) < 0
1484b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1485b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg1(tcp, &state, &tcp->inst[1]) < 0
14863291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		    || change_syscall(tcp, clone_scno[current_personality]) < 0
1487b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1488b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg1(tcp, &state, 0) < 0
1489b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || arg_finish_change(tcp, &state) < 0)
1490d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1491c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1492c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1493d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1494d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
14953bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1496d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1497d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone:
14983bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_clone2
1499d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone2:
15003bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
15018fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
15028fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   contrary to x86 SYS_vfork above.  Even on x86 we turn the
15038fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
15048fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
15058fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
15068fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
15078fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
15088fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1509b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if ((arg_setup(tcp, &state) < 0
1510b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg0(tcp, &state,
1511d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath				 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
15128fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
15138fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				     ? CLONE_VFORK | CLONE_VM : 0)) < 0
1514b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || arg_finish_change(tcp, &state) < 0))
15155ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			return -1;
1516d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1517c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1518c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1519d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1520d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1521d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1522d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1523d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1524d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1525d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1526d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1527d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1528d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1529d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1530d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
15311201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
1532d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1533d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1534b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (arg_setup(tcp, &state) < 0
1535b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1536b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1537b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || arg_finish_change(tcp, &state))
153846ed50d56909843420b0a0cb1360a500ce421d52Andreas Schwab		if (errno != ESRCH) return -1;
1539d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1540d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1541d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1542d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
15433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# else /* !defined LINUX */
1544d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
15461201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkosetbpt(struct tcb *tcp)
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15483bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
15493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC	/* This code is slightly sparc specific */
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1551e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
15523bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define BPT	0x91d02001	/* ta	1 */
15533bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOP	0x10800000	/* ba	0 */
15543bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOPA	0x30800000	/* ba,a	0 */
15553bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define NOP	0x01000000
15563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if LOOPA
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
15583bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    else
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
15603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1566eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1567eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
1571eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1572eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				sizeof tcp->inst, (char *)tcp->inst) < 0) {
1573eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1587eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
1589eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15943bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
15953bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
16011201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16033bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
16043bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16063bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
1607e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
16083bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1614eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
1616eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
16243bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko	 * to adjust the program counter after removing our `breakpoint'.
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1626eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1627eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1630eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if ((regs.r_pc < tcp->baddr) ||
1631eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				(regs.r_pc > tcp->baddr + 4)) {
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
16363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko					regs.r_pc, tcp->baddr);
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
1645eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1646eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16493bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif /* LOOPA */
16503bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
16513bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !defined LINUX */
1657d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1658bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16641201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkogetex(struct tcb *tcp, struct exec *hdr)
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
1670932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
16841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkofixvfork(struct tcb *tcp)
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1697932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (getex(tcp, &hdr) < 0)
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
171146100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1714eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
1732eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
1745