util.c revision e5e60858063f214fcd7860f50f8bcb46f951f9ab
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
9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_nz(a)
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *a;
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return a->tv_sec || a->tv_usec;
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_cmp(a, b)
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *a, *b;
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec < b->tv_sec
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec > b->tv_sec
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandouble
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_float(tv)
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv;
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return tv->tv_sec + tv->tv_usec/1000000.0;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_add(tv, a, b)
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a, *b;
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec + b->tv_sec;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec + b->tv_usec;
12958372f52ac5f824be687c01bfc1db1ffb963f91eRoland McGrath	if (tv->tv_usec >= 1000000) {
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec++;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec -= 1000000;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_sub(tv, a, b)
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a, *b;
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec - b->tv_sec;
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec - b->tv_usec;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (((long) tv->tv_usec) < 0) {
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec--;
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec += 1000000;
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_div(tv, a, n)
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint n;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantv_mul(tv, a, n)
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct timeval *tv, *a;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint n;
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec * n;
163fefdd97156bb2f86c5b6596dc7e28d954516b3edDmitry V. Levin	tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinconst char *
168ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinxlookup(const struct xlat *xlat, int val)
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (; xlat->str != NULL; xlat++)
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val == val)
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return xlat->str;
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
177eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Generic ptrace wrapper which tracks ESRCH errors
178eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * by setting tcp->ptrace_errno to ESRCH.
179732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko *
180732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * We assume that ESRCH indicates likely process death (SIGKILL?),
181732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * modulo bugs where process somehow ended up not stopped.
182732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Unfortunately kernel uses ESRCH for that case too. Oh well.
183eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath *
184eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Currently used by upeek() only.
185eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * TODO: use this in all other ptrace() calls while decoding.
186732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
187732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkolong
188eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathdo_ptrace(int request, struct tcb *tcp, void *addr, void *data)
189732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
190732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	long l;
191732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
192732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
19309a13c2da736aa9a74e7de761062c82832f7cf04Mike Frysinger	l = ptrace(request, tcp->pid, addr, (long) data);
194eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	/* Non-ESRCH errors might be our invalid reg/mem accesses,
195eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	 * we do not record them. */
196eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (errno == ESRCH)
197eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		tcp->ptrace_errno = ESRCH;
198732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return l;
199732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
200732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
201732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
202732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Used when we want to unblock stopped traced process.
203732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
204732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Returns 0 on success or if error was ESRCH
205732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * (presumably process was killed while we talk to it).
206732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko * Otherwise prints error message and returns -1.
207732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko */
208732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenkoint
209eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathptrace_restart(int op, struct tcb *tcp, int sig)
210732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko{
211732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	int err;
212eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	const char *msg;
213732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
214732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	errno = 0;
21509a13c2da736aa9a74e7de761062c82832f7cf04Mike Frysinger	ptrace(op, tcp->pid, (void *) 1, (long) sig);
216732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	err = errno;
217732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (!err || err == ESRCH)
218732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		return 0;
219732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
220732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	tcp->ptrace_errno = err;
221eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	msg = "SYSCALL";
222eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (op == PTRACE_CONT)
223eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		msg = "CONT";
224eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (op == PTRACE_DETACH)
225eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		msg = "DETACH";
226eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
227eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			msg, sig, strerror(err));
228732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	return -1;
229732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko}
230732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko
231732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko/*
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
235ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
237ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", str);
24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
245b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#if HAVE_LONG_LONG
246b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab/*
247b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * Print 64bit argument at position llarg and return the index of the next
248b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * argument.
249b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab */
250b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabint
251b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabprintllval(struct tcb *tcp, const char *format, int llarg)
252b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab{
253b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# if defined(FREEBSD) \
254b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab     || (defined(LINUX) && defined(POWERPC) && !defined(__powerpc64__)) \
255b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab     || defined (LINUX_MIPSO32)
256b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	/* Align 64bit argument to 64bit boundary.  */
257b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	if (llarg % 2) llarg++;
258b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# endif
259b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# if defined LINUX && defined X86_64
260b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	if (current_personality == 0) {
261b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, tcp->u_arg[llarg]);
262b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg++;
263b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	} else {
264b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
265b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg += 2;
266b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	}
267b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# elif defined IA64 || defined ALPHA || (defined POWERPC && defined __powerpc64__)
268b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->u_arg[llarg]);
269b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
270b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# elif defined LINUX_MIPSN32
271b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->ext_arg[llarg]);
272b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
273b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# else
274b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
275b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg += 2;
276b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# endif
277b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	return llarg;
278b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab}
279b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#endif
280b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanaddflags(xlat, flags)
288d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n++;
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
307a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
308a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Interpret `xlat' as an array of flags/
309a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
310a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
311a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
312a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
313a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
314a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
315a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
316a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
317a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
318a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	strcpy(outstr, prefix);
319a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
320a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
321a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
322a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
323a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath				strcat(outstr, "|");
324a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, xlat->str);
325a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			flags &= ~xlat->val;
326a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
327a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
328a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
329a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
330a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
331a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			strcat(outstr, "|");
332a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		sprintf(outstr + strlen(outstr), "%#x", flags);
333a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
334a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
335a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
336a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
337a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
339b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathprintflags(xlat, flags, dflt)
340d9f816f60457930af27349fac3d23b3b78338036Roland McGrathconst struct xlat *xlat;
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint flags;
342b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrathconst char *dflt;
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *sep;
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
34876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s", xlat->str);
34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
35176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
35376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
35476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
35576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
35676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
35776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
35876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
35976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
36076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
361b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
362b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
363b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
364b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
365b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
366b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
367b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
368b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
369b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
370b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
371b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
372b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
373b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
374b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf("0");
375b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
377b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintnum(tcp, addr, fmt)
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
387eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
39676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[");
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("]");
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
4026bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
4039814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathprintnum_int(tcp, addr, fmt)
4049814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathstruct tcb *tcp;
4059814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathlong addr;
4069814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathchar *fmt;
4079814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
4089814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
4099814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4109814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
4119814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("NULL");
4129814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4139814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
4149814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
4159814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
4169814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4179814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
4189814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("[");
4199814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
4209814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf("]");
4219814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
4229814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4239814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4246bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathprintuid(text, uid)
4256bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathconst char *text;
4266bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathunsigned long uid;
4276bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4286bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf("%s", text);
4296bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath	tprintf((uid == -1) ? "%ld" : "%lu", uid);
4306bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4316bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic char path[MAXPATHLEN + 1];
43376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
434a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
435a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
436a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
437a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat `instr' as a NUL-terminated string
438a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
439a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
4406d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrathstatic int
441bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinstring_quote(const char *instr, char *outstr, int len, int size)
44276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
443bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
444bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
445bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	int usehex = 0, c, i;
44676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
447bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
448bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
449bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
450a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
451a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
452bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
453bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
454a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
455a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
456a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
457a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
458a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
459a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
460a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
461a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
462bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
463bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
464bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
465bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
466bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
468bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
469bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
470bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
471bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
472a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
473bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
475a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
476a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
477a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
478a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
479a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
480a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
481a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
482a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
483bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			sprintf(s, "\\x%02x", c);
484bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			s += 4;
485bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
486bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
487bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
488bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
489a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
490a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			if (len < 0) {
491a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (c == '\0')
492a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					break;
493a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				/* Quote at most size - 1 bytes. */
494a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin				if (i == size - 1)
495a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin					continue;
496a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			}
497bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
498bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
500bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
502bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
503bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
505bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
509bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
510bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
511bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
512bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
513bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
518bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
520bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
521bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
522bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
523bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
524bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
525bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					else if (i + 1 < size
526bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						 && isdigit(ustr[i + 1])) {
527bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%03o", c);
528bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += 4;
529bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					} else {
530bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						sprintf(s, "\\%o", c);
531bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						s += strlen(s);
532bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
533bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
534bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
538bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
539bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
5406d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
5416d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	/* Return nonzero if the string was unterminated.  */
5426d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	return i == size;
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
545a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
546a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
547a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
548a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
550bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
552a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
553371ed8fceca7e2812a5edbaab2db2cce966dc0e8Roland McGrath		tprintf("NULL");
554bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
555bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
556bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
557a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Cap path length to the path buffer size,
558a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	   and NUL-terminate the buffer. */
559a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
560a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
561bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	path[n] = '\0';
562a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
563a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
564bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (umovestr(tcp, addr, n + 1, path) < 0)
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
567bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
568bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		int trunc = (path[n] != '\0');
569bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
570bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (trunc)
571bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			path[n] = '\0';
572a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		(void) string_quote(path, outstr, -1, n + 1);
573a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		if (trunc)
574bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			strcat(outstr, "...");
575bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		tprintf("%s", outstr);
57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
580bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
581bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
582bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	printpathn(tcp, addr, sizeof path - 1);
583bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
584bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
585a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
586a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
587a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
588a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
589a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
590bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
591bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintstr(struct tcb *tcp, long addr, int len)
59276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
593bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
5956d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("NULL");
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
60076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
601a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
602a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str)
603a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
604a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!outstr)
605a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		outstr = malloc(4 * max_strlen + sizeof "\"...\"");
606a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!str || !outstr) {
607a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		fprintf(stderr, "out of memory\n");
608a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		tprintf("%#lx", addr);
609a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		return;
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
611bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (len < 0) {
613a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
614a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
615a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
616a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
617bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
618a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str[max_strlen] = '\0';
619bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
625a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		size = MIN(len, max_strlen);
626bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
632a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (string_quote(str, outstr, len, size) &&
633a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	    (len < 0 || len > max_strlen))
634bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		strcat(outstr, "...");
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("%s", outstr);
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6391d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6401d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6411d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesdumpiov(tcp, len, addr)
6421d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesstruct tcb * tcp;
6431d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesint len;
6441d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hugheslong addr;
6451d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6464ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
6474ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6484ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6494ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6504ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6514ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6524ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6534ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6544ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6554ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6564ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6574ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6584ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6594ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin  (personality_wordsize[current_personality] == 4 \
6604ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin   ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6614ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6621d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6634ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6644ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6654ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6664ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6671d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
668aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	unsigned long size;
6691d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
6704ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	size = sizeof_iov * (unsigned long) len;
6714ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	if (size / sizeof_iov != len
6724ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
673aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath		fprintf(stderr, "out of memory\n");
6741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		return;
6751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
676aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
6771d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
678adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			/* include the buffer number to make it easy to
679adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			 * match up the trace with the source */
680adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			tprintf(" * %lu bytes in buffer %d\n",
681adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				(unsigned long)iov_iov_len(i), i);
682adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			dumpstr(tcp, (long) iov_iov_base(i),
683adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				iov_iov_len(i));
684adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		}
6851d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
6861d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	free((char *) iov);
6874ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6884ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6894ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6904ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6911d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6921d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6931d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandumpstr(tcp, addr, len)
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanlong addr;
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint len;
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char outstr[80];
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (str)
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			free(str);
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((str = malloc(len)) == NULL) {
71046100d07257824da2ae1147da0324b5788c95501Roland McGrath			fprintf(stderr, "out of memory\n");
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
757ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumoven(struct tcb *tcp, long addr, int len, char *laddr)
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
760eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
7625daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
772eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
773eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
774eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
775eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
776eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
779eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* But if not started, we had a bogus address. */
780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
781eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
782eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
783eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
7845daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
789eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
790eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
791eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
792eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
793eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
794eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
795eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
796eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
797eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("ptrace: umoven");
798eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
799eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
8005daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(len, PAGSIZ);
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
813eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(PTRACE_READDATA, pid,
814eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			   (char *) addr, len, laddr) < 0) {
815eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (errno != ESRCH) {
816eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umoven: ptrace(PTRACE_READDATA, ...)");
817eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				abort();
818eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		len -= n;
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += n;
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		laddr += n;
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
827bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
828ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
829aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
8309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
831aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
833aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
834aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	if (read(fd, laddr, len) == -1)
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * like `umove' but make the additional effort of looking
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
846ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumovestr(struct tcb *tcp, long addr, int len, char *laddr)
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
848bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
849aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#ifdef HAVE_MP_PROCFS
850aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd_as;
851aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#else
852aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int fd = tcp->pfd;
853aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes#endif
854aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	/* Some systems (e.g. FreeBSD) can be upset if we read off the
855aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   end of valid memory,  avoid this by trying to read up
856aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   to page boundaries.  But we don't know what a page is (and
857aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   getpagesize(2) (if it exists) doesn't necessarily return
858aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   hardware page size).  Assume all pages >= 1024 (a-historical
859aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	   I know) */
860aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
861aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int page = 1024; 	/* How to find this? */
862aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int move = page - (addr & (page - 1));
863aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	int left = len;
864aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
865aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	lseek(fd, addr, SEEK_SET);
866aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes
867aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	while (left) {
868aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (move > left) move = left;
8699cecf7f8d6115a247be7186013857270b2d588d5John Hughes		if ((move = read(fd, laddr, move)) <= 0)
870aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes			return left != len ? 0 : -1;
871aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		if (memchr (laddr, 0, move)) break;
872aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		left -= move;
873aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		laddr += move;
874aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		addr += move;
875aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes		move = page;
876aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	}
877bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
8785daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman	int started = 0;
879eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
890eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
891eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
892eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
893eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
894eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
895eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
896eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
897eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
898eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
899eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
900eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9015daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
909eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
910eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
911eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
912eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
913eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
914eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
915eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
916eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
917eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("umovestr");
918eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
919eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9205daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(laddr, u.x, m = MIN(sizeof(long), len));
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
928bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
929aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
9333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# if !defined (SPARC) && !defined(SPARC64)
9343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITETEXT	101
9353bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  define PTRACE_WRITEDATA	102
9363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !SPARC && !SPARC64 */
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
942eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathuload(cmd, pid, addr, len, laddr)
943eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint cmd;
944eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint pid;
945eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathlong addr;
946eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint len;
947eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathchar *laddr;
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int peek, poke;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cmd == PTRACE_WRITETEXT) {
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKTEXT;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKETEXT;
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		peek = PTRACE_PEEKDATA;
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		poke = PTRACE_POKEDATA;
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long);
968eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
969eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(peek, pid, (char *) addr, 0);
970eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
971eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
973eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
974eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
975eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
976eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
979eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (len < sizeof(long))
983eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			u.val = ptrace(peek, pid, (char *) addr, 0);
984eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		memcpy(u.x, laddr, m = MIN(sizeof(long), len));
985eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
986eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror("uload: POKE");
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
989eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		addr += sizeof(long), laddr += m, len -= m;
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
994eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
995eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtload(pid, addr, len, laddr)
996eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint pid;
997eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint addr, len;
998eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathchar *laddr;
999eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath{
1000eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1001eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath}
1002eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
1003eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint
1004eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathdload(pid, addr, len, laddr)
1005eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint pid;
1006eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint addr;
1007eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathint len;
1008eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathchar *laddr;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1010eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1015bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1018eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathupeek(tcp, off, res)
1019eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp;
1020eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathlong off;
1021eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathlong *res;
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10253bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	{
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static int is_sun4m = -1;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct utsname name;
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Round up the usual suspects. */
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m == -1) {
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (uname(&name) < 0) {
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("upeek: uname?");
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			is_sun4m = strcmp(name.machine, "sun4m") == 0;
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (is_sun4m) {
1038d9f816f60457930af27349fac3d23b3b78338036Roland McGrath				const struct xlat *x;
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				for (x = struct_user_offsets; x->str; x++)
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					x->val += 1024;
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (is_sun4m)
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			off += 1024;
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
10473bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1048eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1049732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1050eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (val == -1 && errno) {
1051eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno != ESRCH) {
1052eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			char buf[60];
1053eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1054eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			perror(buf);
1055eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1057eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	}
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1062bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1065ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenkoprintcall(struct tcb *tcp)
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10677a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
10687a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   sizeof(long) == 8 ? "[????????????????] " : \
10697a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath			   NULL /* crash */)
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
10723bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# ifdef I386
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long eip;
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1075932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*EIP, &eip) < 0) {
10767a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", eip);
1080eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10813bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(S390) || defined(S390X)
1082adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long psw;
1083eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
1084adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		PRINTBADPC;
1085adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1086adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
10873bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef S390
1088adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", psw);
10893bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif S390X
1090adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%16lx] ", psw);
10913bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1092eac26fc53eaf2cd52c1c531d1d3817a66b8b2180Roland McGrath
10933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(X86_64)
10940e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	long rip;
10950e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig
1096932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 8*RIP, &rip) < 0) {
10977a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
10980e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig		return;
10990e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	}
11000e035502d28ef981636abde3139247e6fb2bfcceMichal Ludvig	tprintf("[%16lx] ", rip);
11013bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(IA64)
11028b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	long ip;
11038b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
1104932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_B0, &ip) < 0) {
11057a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
11068b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman		return;
11078b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	}
11088b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman	tprintf("[%08lx] ", ip);
11093bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(POWERPC)
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1112932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(M68K)
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1120932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*PT_PC, &pc) < 0) {
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf ("[????????] ");
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11253bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ALPHA)
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long pc;
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1128932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
11297a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08lx] ", pc);
11333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SPARC) || defined(SPARC64)
11348566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	struct pt_regs regs;
1135eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
11367a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11398566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  if defined(SPARC64)
11408566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.tpc);
11418566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  else
11428566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger	tprintf("[%08lx] ", regs.pc);
11438566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#  endif
11443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(HPPA)
1145c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	long pc;
1146c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman
1147eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
1148c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		tprintf ("[????????] ");
1149c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman		return;
1150c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	}
1151c1652e2095fcd9ac62cf2669ef6aec5fd0052851Wichert Akkerman	tprintf("[%08lx] ", pc);
11523bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(MIPS)
115375c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	long pc;
115475c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman
1155932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_EPC, &pc) < 0) {
115675c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		tprintf ("[????????] ");
115775c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman		return;
115875c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	}
115975c422b3a8c2eecc403f14a00e14f7675149dd07Wichert Akkerman	tprintf("[%08lx] ", pc);
11603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH)
1161adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	long pc;
1162ccef63782c10d9ce9da77ef7530861a3d14b1300Wichert Akkerman
1163adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1164adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		tprintf ("[????????] ");
1165adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		return;
1166adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	}
1167adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko	tprintf("[%08lx] ", pc);
11683bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(SH64)
1169e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	long pc;
1170e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1171932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
11727a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		tprintf ("[????????????????] ");
1173e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath		return;
1174e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	}
1175e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath	tprintf("[%08lx] ", pc);
11763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(ARM)
1177ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	long pc;
1178e1e584b8fa0d97caad461f82a5427cd37d6327f3Roland McGrath
1179932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, 4*15, &pc) < 0) {
11807a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
1181ef388689610fa17df1d3001face8057b411a2e26Roland McGrath		return;
1182ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	}
1183ef388689610fa17df1d3001face8057b411a2e26Roland McGrath	tprintf("[%08lx] ", pc);
11845ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko# elif defined(AVR32)
11855ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	long pc;
11865ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko
11875ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	if (upeek(tcp, REG_PC, &pc) < 0) {
11885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		tprintf("[????????] ");
11895ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return;
11905ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	}
11915ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko	tprintf("[%08lx] ", pc);
11923bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# elif defined(BFIN)
119387ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	long pc;
119487ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin
1195932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_PC, &pc) < 0) {
119687ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		PRINTBADPC;
119787ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin		return;
119887ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	}
119987ea1f4fe68c6110a96a76f8601b3e204200082dDmitry V. Levin	tprintf("[%08lx] ", pc);
1200ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV10)
1201ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1202ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1203eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1204ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1205ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1206ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1207ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
1208ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#elif defined(CRISV32)
1209ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	long pc;
1210ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko
1211eeb9ce3895f1ca0920d50696ef8b48124cef9da6Edgar E. Iglesias	if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1212ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		PRINTBADPC;
1213ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko		return;
1214ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	}
1215ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko	tprintf("[%08lx] ", pc);
12163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* architecture */
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct regs regs;
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1222eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1223eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("printcall: ptrace(PTRACE_GETREGS, ...)");
12247a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath		PRINTBADPC;
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("[%08x] ", regs.r_o7);
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* XXX */
12327a91883b32776a7fc8255ddbcf2d1781be9e2c2eRoland McGrath	PRINTBADPC;
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1235bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1236bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct reg regs;
1237bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1238bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	tprintf("[%08x] ", regs.r_eip);
1239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12423bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
12433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko/*
12443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * These #if's are huge, please indent them correctly.
12453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * It's easy to get confused otherwise.
12463bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko */
1247bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1249e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levin#ifdef LINUX
1250d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12513bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include "syscall.h"
12523291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
12533bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  include <sys/syscall.h>
12543bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_PTRACE
12553bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_PTRACE    0x00002000
12563bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12573bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VFORK
12583bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VFORK     0x00004000
12593bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12603bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_VM
12613bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_VM        0x00000100
12623bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
12633bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef CLONE_STOPPED
12643bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define CLONE_STOPPED   0x02000000
12653bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1266d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12673bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef IA64
1268d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
126908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
127008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath   subsystem has them for x86... */
12713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_fork	2
12723bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define SYS_vfork	190
127308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1274d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1275d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1276d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1277d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1278d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
12791f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
12801f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1281d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12821f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
12831f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
12841f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
128508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
12861f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
128708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1288932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1289d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1290932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1291d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1292d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1293d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1294d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
12951f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1296d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12971f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1298d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1299d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1300d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13013bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
1302d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13033bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SYS_fork
1304d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1305d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1306d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
130708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
130808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
130908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1310932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		ret = upeek (tcp, PT_R11, valp);
131108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
131208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
131308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
131408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
131508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1316d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1317d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1318d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1319d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathget_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1320d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
132108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
132208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
132308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1324932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		ret = upeek (tcp, PT_R9, valp);
132508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
132608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ret = umoven (tcp,
132708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
132808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
132908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1330d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
13313bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1332d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1333d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1334d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1335d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
133608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
133708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
133808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
133908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
134008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
134108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
134208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
134308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1344eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1345eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1346eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1347d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1348d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1349d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1350d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathset_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1351d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
135208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
135308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
135408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
135508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
135608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
135708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
135808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
135908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1360eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1361eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1362eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1363d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1364d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1365b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1366b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1367b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13683bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) ((void) (state), 0)
13693bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) ((void) (state), 0)
1370b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
13713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  elif defined (SPARC) || defined (SPARC64)
1372d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13738566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysingertypedef struct pt_regs arg_setup_state;
1374d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13753bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) \
1376eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath    (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
13773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state) \
1378eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath    (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1379d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13808566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
13818566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
13828566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
13838566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysinger#   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
13843bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) 0
1385d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13863bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  else /* other architectures */
1387d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13883bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   if defined S390 || defined S390X
13897b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
13907b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
13917b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
13927b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
13933bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	PT_GPR3
13943bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	PT_ORIGGPR2
13953bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
13963bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg1(tcp, state, val) ((void) (state), 0)
13973bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_index	1
13983bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_index	0
13993bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (ALPHA) || defined (MIPS)
14003bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	REG_A0
14013bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(REG_A0+1)
14025ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#   elif defined (AVR32)
14035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg0_offset	(REG_R12)
14045ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#    define arg1_offset	(REG_R11)
14053bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (POWERPC)
14063bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(sizeof(unsigned long)*PT_R3)
14073bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(sizeof(unsigned long)*PT_R4)
14083bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) ((void) (state), 0)
14093bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (HPPA)
14103bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	 PT_GR26
14113bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	 (PT_GR26-4)
14123bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (X86_64)
14133bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
14143bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
14153bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH)
14163bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	(4*(REG_REG0+4))
14173bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	(4*(REG_REG0+5))
14183bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   elif defined (SH64)
14193bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko    /* ABI defines arg0 & 1 in r2 & r3 */
14203bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset   (REG_OFFSET+16)
14213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset   (REG_OFFSET+24)
14223bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define restore_arg0(tcp, state, val) 0
1423ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#   elif defined CRISV10 || defined CRISV32
1424ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_offset   (4*PT_R11)
1425ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_offset   (4*PT_ORIG_R10)
1426ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg0(tcp, state, val) 0
1427ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define restore_arg1(tcp, state, val) 0
1428ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg0_index   1
1429ea0e6e80260d2b1b7ad40282012b0e47869bcddfDenys Vlasenko#    define arg1_index   0
14303bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   else
14313bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg0_offset	0
14323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define arg1_offset	4
14333bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if defined ARM
14343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#     define restore_arg0(tcp, state, val) 0
14353bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
14363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif
1437d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1438d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1439d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14403bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_setup(tcp, state) (0)
14413bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg_finish_change(tcp, state)	0
14423bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg0(tcp, cookie, valp) \
14433bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko    (upeek ((tcp), arg0_offset, (valp)))
14443bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define get_arg1(tcp, cookie, valp) \
14453bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko    (upeek ((tcp), arg1_offset, (valp)))
1446d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1447d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1448eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathset_arg0 (struct tcb *tcp, void *cookie, long val)
1449d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1450eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1451d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1452d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1453d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1454eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathset_arg1 (struct tcb *tcp, void *cookie, long val)
1455d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1456eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1457d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1458d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14593bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* architectures */
1460d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14613bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg0
14623bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
14633bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
14643bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef restore_arg1
14653bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
14663bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1467d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14683bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifndef arg0_index
14693bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg0_index 0
14703bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   define arg1_index 1
14713bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
147290d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
1473d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1474418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkosetbpt(struct tcb *tcp)
1475d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
14763291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1477d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1478d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1479d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1480d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1481d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1482d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1483d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14843291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
14853291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
14863291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
14873291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
14883291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
14893291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
14903291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
14913291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
14923291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
14933291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
14943291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
14953291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
14963291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
14973291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
149876989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath	switch (known_scno(tcp)) {
14993bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_vfork
15009383c6c539af09303efe0a16dea55363b095f66eRoland McGrath	case SYS_vfork:
15013bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
15023bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_fork
1503d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_fork:
15043bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
15053bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  if defined SYS_fork || defined SYS_vfork
1506d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		if (arg_setup (tcp, &state) < 0
1507d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1508d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
15093291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		    || change_syscall(tcp, clone_scno[current_personality]) < 0
1510d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1511d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || set_arg1 (tcp, &state, 0) < 0
1512d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		    || arg_finish_change (tcp, &state) < 0)
1513d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1514c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1515c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1516d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1517d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
15183bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
1519d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1520d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone:
15213bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SYS_clone2
1522d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	case SYS_clone2:
15233bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif
15248fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
15258fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   contrary to x86 SYS_vfork above.  Even on x86 we turn the
15268fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
15278fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
15288fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
15298fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
15308fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
15318fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1532d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		if ((arg_setup (tcp, &state) < 0
1533d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || set_arg0 (tcp, &state,
1534d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath				 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
15358fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
15368fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil				     ? CLONE_VFORK | CLONE_VM : 0)) < 0
1537d6ff0d520d4bd8dda1523ec57e8ba2bc0ab3cf69Roland McGrath		    || arg_finish_change (tcp, &state) < 0))
15385ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			return -1;
1539d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1540c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1541c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
1542d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1543d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1544d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	default:
1545d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1546d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			tcp->scno, tcp->pid);
1547d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		break;
1548d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1549d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1550d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1551d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1552d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1553d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1554d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathclearbpt(tcp)
1555d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstruct tcb *tcp;
1556d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1557d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1558d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (arg_setup (tcp, &state) < 0
1559e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1560e1df47ff9a7f3e1ed90969109258f2686f74ce0dRoland McGrath	    || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1561d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	    || arg_finish_change (tcp, &state))
156246ed50d56909843420b0a0cb1360a500ce421d52Andreas Schwab		if (errno != ESRCH) return -1;
1563d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1564d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1565d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1566d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
15673bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# else /* !defined LINUX */
1568d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermansetbpt(tcp)
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15733bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
15743bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC	/* This code is slightly sparc specific */
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1576e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
15773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define BPT	0x91d02001	/* ta	1 */
15783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOP	0x10800000	/* ba	0 */
15793bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define LOOPA	0x30800000	/* ba,a	0 */
15803bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    define NOP	0x01000000
15813bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if LOOPA
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[1] = {LOOPA};
15833bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    else
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int loopdeloop[2] = {LOOP, NOP};
15853bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET) {
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1591eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1592eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->baddr = regs.r_o7 + 8;
1596eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1597eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				sizeof tcp->inst, (char *)tcp->inst) < 0) {
1598eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * XXX - BRUTAL MODE ON
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * We cannot set a real BPT in the child, since it will not be
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * traced at the moment it will reach the trap and would probably
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * die with a core dump.
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Thus, we are force our way in by taking out two instructions
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * and insert an eternal loop in stead, in expectance of the SIGSTOP
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * generated by out PTRACE_ATTACH.
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Of cause, if we evaporate ourselves in the middle of all this...
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1612eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sizeof loopdeloop, (char *) loopdeloop) < 0) {
1614eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags |= TCB_BPTSET;
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16193bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
16203bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanclearbpt(tcp)
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16293bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  ifdef SUNOS4
16303bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   ifdef SPARC
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16323bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
1633e6f876c49de4a5f535e476804e4627f8e0ecb869Wichert Akkerman	struct regs regs;
16343bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_BPTSET)) {
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1640eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sizeof tcp->inst, (char *) tcp->inst) < 0) {
1642eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_BPTSET;
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16473bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    if !LOOPA
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Since we don't have a single instruction breakpoint, we may have
16503bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko	 * to adjust the program counter after removing our `breakpoint'.
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
1652eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1653eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1656eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if ((regs.r_pc < tcp->baddr) ||
1657eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				(regs.r_pc > tcp->baddr + 4)) {
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The breakpoint has not been reached yet */
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",
16623bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko					regs.r_pc, tcp->baddr);
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 0;
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (regs.r_pc != tcp->baddr)
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				regs.r_pc, tcp->baddr);
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	regs.r_pc = tcp->baddr;
1671eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1672eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16753bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#    endif /* LOOPA */
16763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#   endif /* SPARC */
16773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#  endif /* SUNOS4 */
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16823bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko# endif /* !defined LINUX */
1683d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1684bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16863bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
1690932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkogetex(tcp, hdr)
1691932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenkostruct tcb *tcp;
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct exec *hdr;
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; n < sizeof *hdr; n += 4) {
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long res;
1698932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko		if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		memcpy(((char *) hdr) + n, &res, 4);
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (debug) {
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfixvfork(tcp)
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid = tcp->pid;
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Change `vfork' in a freshly exec'ed dynamically linked
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * executable's (internal) symbol table to plain old `fork'
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct exec hdr;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic dyn;
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct link_dynamic_2 ld;
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *strtab, *cp;
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1726932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (getex(tcp, &hdr) < 0)
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!hdr.a_dynamic)
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read DYNAMIC\n");
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Cannot read link_dynamic_2\n");
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
174046100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "out of memory\n");
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1743eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		goto err;
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strcmp(cp, "_vfork") == 0) {
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "fixvfork: FOUND _vfork\n");
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(cp, "_fork");
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		cp += strlen(cp)+1;
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cp < strtab + ld.ld_symb_size)
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Write entire symbol table back to avoid
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * memory alignment bugs in ptrace
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
1761eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(int)ld.ld_symb_size, strtab) < 0)
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto err;
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanerr:
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	free(strtab);
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return -1;
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
1774