util.c revision bf357fcb76baeb64a45fc2b6b355c913c63e6015
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
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/user.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
381d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
392d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# include <sys/uio.h>
401d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
4136915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman
428470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if defined(IA64)
43d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# include <asm/ptrace_offsets.h>
44d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath# include <asm/rse.h>
458b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
468b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman
4736915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman#ifdef HAVE_SYS_REG_H
488470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko# include <sys/reg.h>
4936915a19e4806339b76209b20fdbd1091c126115Wichert Akkerman# define PTRACE_PEEKUSR PTRACE_PEEKUSER
50faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(HAVE_LINUX_PTRACE_H)
518470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko# undef PTRACE_SYSCALL
52ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_IA64_FPREG
53ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define ia64_fpreg XXX_ia64_fpreg
54ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
55ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define pt_all_user_regs XXX_pt_all_user_regs
57ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
588470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko# include <linux/ptrace.h>
59ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef ia64_fpreg
60ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef pt_all_user_regs
612e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman#endif
622e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman
6376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* macros */
6476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MAX
652d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define MAX(a,b)		(((a) > (b)) ? (a) : (b))
6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef MIN
682d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define MIN(a,b)		(((a) < (b)) ? (a) : (b))
6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
72ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstring_to_uint(const char *str)
73ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin{
74ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	char *error;
75ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	long value;
76ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
77ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	if (!*str)
78ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin		return -1;
79ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	errno = 0;
80ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	value = strtol(str, &error, 10);
81ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	if (errno || *error || value < 0 || (long)(int)value != value)
82ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin		return -1;
83ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	return (int)value;
84ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin}
85ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
86ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinint
871201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_nz(struct timeval *a)
8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return a->tv_sec || a->tv_usec;
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
931201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_cmp(struct timeval *a, struct timeval *b)
9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec < b->tv_sec
9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec > b->tv_sec
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandouble
1051201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_float(struct timeval *tv)
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return tv->tv_sec + tv->tv_usec/1000000.0;
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec + b->tv_sec;
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec + b->tv_usec;
11558372f52ac5f824be687c01bfc1db1ffb963f91eRoland McGrath	if (tv->tv_usec >= 1000000) {
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec++;
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec -= 1000000;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1221201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec - b->tv_sec;
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec - b->tv_usec;
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (((long) tv->tv_usec) < 0) {
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec--;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec += 1000000;
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1331201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_div(struct timeval *tv, struct timeval *a, int n)
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
1411201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotv_mul(struct timeval *tv, struct timeval *a, int n)
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec * n;
144fefdd97156bb2f86c5b6596dc7e28d954516b3edDmitry V. Levin	tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
148ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinconst char *
149ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinxlookup(const struct xlat *xlat, int val)
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (; xlat->str != NULL; xlat++)
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val == val)
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return xlat->str;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1570a295bc97fd2ba9e6dc02f382dc87bc8705dc4d0Denys Vlasenko#if !defined HAVE_STPCPY
1585284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenkochar *
1595284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenkostpcpy(char *dst, const char *src)
1605284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko{
1615284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	while ((*dst = *src++) != '\0')
1625284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko		dst++;
1635284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	return dst;
1645284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko}
1650a295bc97fd2ba9e6dc02f382dc87bc8705dc4d0Denys Vlasenko#endif
1665284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
171ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
173ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
1765940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(str);
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#if HAVE_LONG_LONG
182b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab/*
183b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * Print 64bit argument at position llarg and return the index of the next
184b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * argument.
185b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab */
186b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabint
187b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabprintllval(struct tcb *tcp, const char *format, int llarg)
188b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab{
189aa925db23634fe6a2c1d4b47accb3649daf1b781Denys Vlasenko# if defined(X86_64) || defined(POWERPC64)
190b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	if (current_personality == 0) {
191b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, tcp->u_arg[llarg]);
192b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg++;
193b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	} else {
194d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  ifdef POWERPC64
195d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab		/* Align 64bit argument to 64bit boundary.  */
1964b08df42ff069dcf44b8ed206ae33a2904c366baDenys Vlasenko		llarg = (llarg + 1) & 0x1e;
197d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab#  endif
198b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
199b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab		llarg += 2;
200b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	}
201d69fa497f4729373618fb7b506a2362422487ab1Andreas Schwab# elif defined IA64 || defined ALPHA
202b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->u_arg[llarg]);
203b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
20435be58119e3727a694d8c9f9b83f372401fcc4c0H.J. Lu# elif defined LINUX_MIPSN32 || defined X32
205b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, tcp->ext_arg[llarg]);
206b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg++;
207b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# else
208b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
209b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	llarg += 2;
210b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab# endif
211b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	return llarg;
212b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab}
213b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab#endif
214b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
2204924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenkovoid
2211201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoaddflags(const struct xlat *xlat, int flags)
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2234924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko	for (; xlat->str; xlat++) {
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
2354924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko * Interpret `xlat' as an array of flags.
236a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
237a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
238a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
239a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
240a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
241a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
242a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
2435284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	char *outptr;
244a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
245a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
2465284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	outptr = stpcpy(outstr, prefix);
247a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
248a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
249a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
250a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
2515284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko				*outptr++ = '|';
2525284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko			outptr = stpcpy(outptr, xlat->str);
253a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
2544f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			flags &= ~xlat->val;
2554f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (!flags)
2564f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				break;
257a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
258a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
259a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
260a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
2615284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko			*outptr++ = '|';
2625284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko		outptr += sprintf(outptr, "%#x", flags);
263a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
264a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
265a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
266a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
267a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
26930145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintflags(const struct xlat *xlat, int flags, const char *dflt)
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
27230145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin	const char *sep;
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
2755940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(xlat->str);
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
288b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
289b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
290b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
291b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
292b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
293b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
294b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
295b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
296b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
297b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
298b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
299b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
300b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
30160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko				tprints("0");
302b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
304b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
30930145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum(struct tcb *tcp, long addr, const char *fmt)
31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
311eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
31460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("[");
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
32360fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("]");
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3266bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
32730145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum_int(struct tcb *tcp, long addr, const char *fmt)
3289814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3299814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3309814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3319814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
33260fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
3339814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3349814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3359814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
3369814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
3379814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3389814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
33960fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("[");
3409814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
34160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("]");
3429814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
3439814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3449814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
3453138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinprintfd(struct tcb *tcp, int fd)
3463138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin{
3478a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	const char *p;
3488a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
3498a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	if (show_fd_path && (p = getfdpath(tcp, fd)))
3508a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d<%s>", fd, p);
3518a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	else
3528a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d", fd);
3533138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin}
3543138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin
3553138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinvoid
3561201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintuid(const char *text, unsigned long uid)
3576bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
3585940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
3596bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
3606bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
361a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
362a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
363a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
364b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko * If `len' is -1, treat `instr' as a NUL-terminated string
365a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
3666cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
367b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
3686cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Note that if len >= 0, always returns 1.
369a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
370ebee04cfb009bdc46599774b4647f6615b6ce3a2Mike Frysingerint
371b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenkostring_quote(const char *instr, char *outstr, long len, int size)
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
373bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
374bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
3758778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	int usehex, c, i, eol;
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3778778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	eol = 0x100; /* this can never match a char */
378b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1) {
3798778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		size--;
3808778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		eol = '\0';
3818778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	}
3828778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
3838778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	usehex = 0;
384bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
385bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
386bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
387a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
388a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
389bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
390bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
391a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
3928778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
3938778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				break;
394bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			if (!isprint(c) && !isspace(c)) {
395bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
396bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
397bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
398bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
400bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
401bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
402bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
403bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
404a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
405bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
406bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
407a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
4088778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
4098778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				goto asciz_ended;
4108778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = '\\';
4118778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = 'x';
4128778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = "0123456789abcdef"[c >> 4];
4138778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = "0123456789abcdef"[c & 0xf];
414bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
415bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
416bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
417bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
418a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
4198778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
4208778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				goto asciz_ended;
421bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
422bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
423bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
424bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
425bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
426bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
427bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
428bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
429bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
430bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
431bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
432bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
433bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
434bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
435bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
436bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
437bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
438bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
439bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
440bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
441bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
442bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
443bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
444bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
445bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
446bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
447bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					if (isprint(c))
448bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
4498778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko					else {
4508778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						/* Print \octal */
4518778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						*s++ = '\\';
4528778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						if (i + 1 < size
4538778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						    && ustr[i + 1] >= '0'
4548778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						    && ustr[i + 1] <= '9'
4558778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						) {
4568778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							/* Print \ooo */
4578778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							*s++ = '0' + (c >> 6);
4588778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							*s++ = '0' + ((c >> 3) & 0x7);
4598778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						} else {
4608778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							/* Print \[[o]o]o */
4618778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							if ((c >> 3) != 0) {
4628778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko								if ((c >> 6) != 0)
4638778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko									*s++ = '0' + (c >> 6);
4648778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko								*s++ = '0' + ((c >> 3) & 0x7);
4658778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							}
4668778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						}
4678778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						*s++ = '0' + (c & 0x7);
468bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
469bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
470bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
475bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
4766d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
4778778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	/* Return zero if we printed entire ASCIZ string (didn't truncate it) */
478b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1 && ustr[i] == '\0') {
4798778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		/* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
4808778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		 * but next char is NUL.
4818778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		 */
4828778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		return 0;
4838778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	}
4848778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
4858778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	return 1;
4868778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
4878778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko asciz_ended:
4888778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	*s++ = '\"';
4898778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	*s = '\0';
4908778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	/* Return zero: we printed entire ASCIZ string (didn't truncate it) */
4918778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	return 0;
49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
494a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
495a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
496a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
497a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
501b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	char path[MAXPATHLEN + 1];
5026cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	int nul_seen;
503b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko
504a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
50560fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
5096cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	/* Cap path length to the path buffer size */
510a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
511a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
512a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
513a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
5146cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	nul_seen = umovestr(tcp, addr, n + 1, path);
5156cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	if (nul_seen < 0)
51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
518b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		char *outstr;
519bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
5206cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		path[n] = '\0';
521b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		n++;
5226cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
523b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		string_quote(path, outstr, -1, n);
524b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		tprints(outstr);
5256cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		if (!nul_seen)
526b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko			tprints("...");
52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
531bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
532bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
533b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	/* Size must correspond to char path[] size in printpathn */
534b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	printpathn(tcp, addr, MAXPATHLEN);
535bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
536bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
537a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
538a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
539a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
540a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
541a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
542bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
543b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenkoprintstr(struct tcb *tcp, long addr, long len)
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
545bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
5476d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
548b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	int ellipsis;
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
55160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
554a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
5551d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!str) {
556378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
557378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin
558378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		if (outstr_size / 4 != max_strlen)
559378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin			die_out_of_memory();
560a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
5611d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		if (!str)
5621d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			die_out_of_memory();
563378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		outstr = malloc(outstr_size);
5641d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		if (!outstr)
5651d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			die_out_of_memory();
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
567bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
568b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1) {
569a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
570a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
571a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
572a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
573bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
574bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
580b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko		size = max_strlen;
581b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko		if (size > (unsigned long)len)
582b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko			size = (unsigned long)len;
583bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
58476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
58776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
5896cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	/* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
5906cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	 * or we were requested to print more than -s NUM chars)...
5916cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	 */
592b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	ellipsis = (string_quote(str, outstr, len, size) &&
593b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko			(len < 0 || len > max_strlen));
59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
595b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	tprints(outstr);
596b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	if (ellipsis)
597b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		tprints("...");
59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6001d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6011d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6021201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpiov(struct tcb *tcp, int len, long addr)
6031d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6048470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1
6054ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6064ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6074ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6084ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6094ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6104ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6119fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6124ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6139fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6144ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6159fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6164ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6171d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6184ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6194ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6204ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6214ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6221d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
62379a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	unsigned size;
6241d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
62579a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	size = sizeof_iov * len;
62679a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	/* Assuming no sane program has millions of iovs */
62779a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	if ((unsigned)len > 1024*1024 /* insane or negative size? */
6284ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
62979a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		fprintf(stderr, "Out of memory\n");
63079a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		return;
6311d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
632aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
6331d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
634adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			/* include the buffer number to make it easy to
635adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			 * match up the trace with the source */
636adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			tprintf(" * %lu bytes in buffer %d\n",
637adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				(unsigned long)iov_iov_len(i), i);
638adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			dumpstr(tcp, (long) iov_iov_base(i),
639adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				iov_iov_len(i));
640adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		}
6411d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
64279a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	free(iov);
6434ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
6444ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
6454ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
6464ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
6471d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
6481d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6491d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
6511201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpstr(struct tcb *tcp, long addr, int len)
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char *s;
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (strsize < len) {
6595d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		free(str);
6605d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		str = malloc(len);
66179a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		if (!str) {
66279a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			strsize = -1;
66379a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			fprintf(stderr, "Out of memory\n");
66479a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			return;
66579a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		}
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		strsize = len;
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < len; i += 16) {
6731d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		char outstr[80];
6741d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s = outstr;
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(s, " | %05x ", i);
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		s += 9;
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				sprintf(s, " %02x", str[i + j]);
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				s += 3;
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' '; *s++ = ' '; *s++ = ' ';
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		*s++ = ' '; *s++ = ' ';
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (j = 0; j < 16; j++) {
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (j == 8)
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (i + j < len) {
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (isprint(str[i + j]))
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = str[i + j];
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					*s++ = '.';
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				*s++ = ' ';
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%s |\n", outstr);
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
706612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#ifdef HAVE_PROCESS_VM_READV
707612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger/* C library supports this, but the kernel might not. */
708612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysingerstatic bool process_vm_readv_not_supported = 0;
709612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#else
710612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger
7113af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko/* Need to do this since process_vm_readv() is not yet available in libc.
7123af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko * When libc is be updated, only "static bool process_vm_readv_not_supported"
7133af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko * line should remain.
7143af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko */
7153af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#if !defined(__NR_process_vm_readv)
7163af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# if defined(I386)
7173af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  347
7183af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# elif defined(X86_64)
7193af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  310
7203af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# elif defined(POWERPC)
7213af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  351
7223af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# endif
7233af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#endif
7243af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
7253af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#if defined(__NR_process_vm_readv)
7263af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenkostatic bool process_vm_readv_not_supported = 0;
72724ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysinger/* Have to avoid duplicating with the C library headers. */
72824ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysingerstatic ssize_t strace_process_vm_readv(pid_t pid,
7293af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 const struct iovec *lvec,
7303af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long liovcnt,
7313af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 const struct iovec *rvec,
7323af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long riovcnt,
7333af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long flags)
7343af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko{
7353af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
7363af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko}
73724ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysinger#define process_vm_readv strace_process_vm_readv
7383af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#else
7393af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenkostatic bool process_vm_readv_not_supported = 1;
7403af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# define process_vm_readv(...) (errno = ENOSYS, -1)
7413af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#endif
742612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger
743612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#endif /* end of hack */
7443af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
751ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumoven(struct tcb *tcp, long addr, int len, char *laddr)
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
753eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n, m;
755a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko	int started;
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
761d2a660f534d98169f60d50706cbb2ec15fa13cf8Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1
7629fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	if (current_wordsize < sizeof(addr))
7639fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko		addr &= (1ul << 8 * current_wordsize) - 1;
764d2a660f534d98169f60d50706cbb2ec15fa13cf8Denys Vlasenko#endif
765d2a660f534d98169f60d50706cbb2ec15fa13cf8Denys Vlasenko
7663af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	if (!process_vm_readv_not_supported) {
7673af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		struct iovec local[1], remote[1];
7683af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		int r;
7693af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
7703af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_base = laddr;
7713af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		remote[0].iov_base = (void*)addr;
7723af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_len = remote[0].iov_len = len;
7733af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		r = process_vm_readv(pid,
7743af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				local, 1,
7753af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				remote, 1,
7763af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				/*flags:*/ 0
7773af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		);
7783af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		if (r < 0) {
7793af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (errno == ENOSYS)
7803af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				process_vm_readv_not_supported = 1;
7819a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin			else if (errno != EINVAL && errno != ESRCH)
7829a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				/* EINVAL or ESRCH could be seen if process is gone,
7839a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				 * all the rest is strange and should be reported. */
7849a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				perror_msg("%s", "process_vm_readv");
7853af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			goto vm_readv_didnt_work;
7863af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		}
7873af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		return r;
7883af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	}
7893af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko vm_readv_didnt_work:
7903af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
791a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko	started = 0;
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
796eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
797eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
798eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
799eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* But if not started, we had a bogus address. */
800eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
8014c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
802eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
803eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
8045daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
805a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long) - n, len);
806a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, &u.x[n], m);
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
810eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
811eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
812eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
813eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
814eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
815eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
816eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
817eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
8184c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
819eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
820eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
8215daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
822a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long), len);
823a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, u.x, m);
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
8316cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Like `umove' but make the additional effort of looking
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
8336cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
8346cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Returns < 0 on error, > 0 if NUL was seen,
8356cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * (TODO if useful: return count of bytes including NUL),
8366cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * else 0 if len bytes were read but no NUL byte seen.
8376cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
8386cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Note: there is no guarantee we won't overwrite some bytes
8396cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * in laddr[] _after_ terminating NUL (but, of course,
8406cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * we never write past laddr[len-1]).
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
843ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumovestr(struct tcb *tcp, long addr, int len, char *laddr)
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
845a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko	int started;
846eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, n, m;
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
853856c7ed97bce524ade99bb1fc41e746973d45accDmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
8549fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	if (current_wordsize < sizeof(addr))
8559fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko		addr &= (1ul << 8 * current_wordsize) - 1;
856856c7ed97bce524ade99bb1fc41e746973d45accDmitry V. Levin#endif
857856c7ed97bce524ade99bb1fc41e746973d45accDmitry V. Levin
8583af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	if (!process_vm_readv_not_supported) {
8593af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		struct iovec local[1], remote[1];
8603af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8613af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_base = laddr;
8623af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		remote[0].iov_base = (void*)addr;
8633af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8643af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		while (len > 0) {
8653af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int end_in_page;
8663af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int r;
8673af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int chunk_len;
8683af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8693af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			/* Don't read kilobytes: most strings are short */
8703af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			chunk_len = len;
8713af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (chunk_len > 256)
8723af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				chunk_len = 256;
8733af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			/* Don't cross pages. I guess otherwise we can get EFAULT
8743af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * and fail to notice that terminating NUL lies
8753af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * in the existing (first) page.
8763af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * (I hope there aren't arches with pages < 4K)
8773af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 */
8783af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			end_in_page = ((addr + chunk_len) & 4095);
8793af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			r = chunk_len - end_in_page;
8803af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (r > 0) /* if chunk_len > end_in_page */
8813af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				chunk_len = r; /* chunk_len -= end_in_page */
8823af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8833af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			local[0].iov_len = remote[0].iov_len = chunk_len;
8843af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			r = process_vm_readv(pid,
8853af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko					local, 1,
8863af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko					remote, 1,
8873af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko					/*flags:*/ 0
8883af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			);
8893af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (r < 0) {
8903af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				if (errno == ENOSYS)
8913af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko					process_vm_readv_not_supported = 1;
8929a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				else if (errno != EINVAL && errno != ESRCH)
8939a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					/* EINVAL or ESRCH could be seen
8949a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					 * if process is gone, all the rest
8959a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					 * is strange and should be reported. */
8969a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					perror_msg("%s", "process_vm_readv");
8973af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				goto vm_readv_didnt_work;
8983af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			}
8993af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (memchr(local[0].iov_base, '\0', r))
9003af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				return 1;
9013af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			local[0].iov_base += r;
9023af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			remote[0].iov_base += r;
9033af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			len -= r;
9043af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		}
9053af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		return 0;
9063af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	}
9073af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko vm_readv_didnt_work:
9083af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
909a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko	started = 0;
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
914eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
915eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
916eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
917eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
9184c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
919eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
920eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9215daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
922a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long) - n, len);
923a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, &u.x[n], m);
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
9266cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko				return 1;
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
930eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
931eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
932eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno) {
933eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (started && (errno==EPERM || errno==EIO)) {
934eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				/* Ran into 'end of memory' - stupid "printpath" */
935eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
936eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			}
937eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (addr != 0 && errno != EIO && errno != ESRCH)
9384c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
939eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return -1;
940eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
9415daa028ca314e4c36c1f38e0149834d9a0520128Wichert Akkerman		started = 1;
942a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long), len);
943a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, u.x, m);
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (i = 0; i < sizeof(long); i++)
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[i] == '\0')
9466cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko				return 1;
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr += sizeof(long), laddr += m, len -= m;
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
949aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
9531201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoupeek(struct tcb *tcp, long off, long *res)
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
957eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
958114aefd6183b8c073453f8def73270c42255f974Denys Vlasenko	val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
959eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (val == -1 && errno) {
960eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno != ESRCH) {
9614c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
962eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
964eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	}
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
969d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
970d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * and PTRACE_O_TRACE[V]FORK for tracing children.
971d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * If you are adding a new arch which is only supported by newer kernels,
972d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * you most likely don't need to add any code below
973d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * beside a dummy "return 0" block in change_syscall().
974d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko */
975d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko
9763bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko/*
9773bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * These #if's are huge, please indent them correctly.
9783bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * It's easy to get confused otherwise.
9793bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko */
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9812d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#include "syscall.h"
9823291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
9832d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_PTRACE
9842d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_PTRACE    0x00002000
9852d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
9862d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_VFORK
9872d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_VFORK     0x00004000
9882d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
9892d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_VM
9902d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_VM        0x00000100
9912d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
992d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
9932d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifdef IA64
994d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
995d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
996d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
997d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
998d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
999d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
10001f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
10011f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1002d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
10031f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	if (ia32) {
10041f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
10051f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
100608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
10071f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
100808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1009932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1010d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1011932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko	if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1012d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1013d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1014d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1015d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
10161f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1017d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
10181f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1019d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1020d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1021d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
10222d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state)	0
1023d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1024d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
10251201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1026d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
102708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
102808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
102908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1030b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R11, valp);
103108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1032b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
103308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
103408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
103508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1036d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1037d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1038d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
10391201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1040d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
104108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
104208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
104308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32)
1044b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = upeek(tcp, PT_R9, valp);
104508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1046b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
104708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
104808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
104908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1050d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1051d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1052d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
10531201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1054d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
105508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
105608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
105708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
105808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
105908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
106008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
106108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
106208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1063eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1064eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1065eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1066d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1067d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1068d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
10691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1070d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
107108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
107208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
107308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
107408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	if (ia32) {
107508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
107608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
107708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
107808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1079eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1080eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1081eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1082d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1083d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1084b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1085b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1086b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
10872d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) ((void) (state), 0)
10882d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg1(tcp, state, val) ((void) (state), 0)
1089b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
10902d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#elif defined(SPARC) || defined(SPARC64)
1091d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1092ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko# if defined(SPARC64)
1093ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  undef PTRACE_GETREGS
1094ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  define PTRACE_GETREGS PTRACE_GETREGS64
1095ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  undef PTRACE_SETREGS
1096ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  define PTRACE_SETREGS PTRACE_SETREGS64
1097ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko# endif
1098ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko
10998566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysingertypedef struct pt_regs arg_setup_state;
1100d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11012d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_setup(tcp, state) \
11022d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko    (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
11032d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state) \
11042d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko    (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
1105d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11062d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
11072d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
11082d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define set_arg0(tcp, state, val)  ((state)->u_regs[U_REG_O0] = (val), 0)
11092d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define set_arg1(tcp, state, val)  ((state)->u_regs[U_REG_O1] = (val), 0)
11102d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) 0
1111d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11122d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#else /* other architectures */
1113d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11142d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# if defined S390 || defined S390X
11157b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
11167b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
11177b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
11187b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
11192d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	PT_GPR3
11202d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	PT_ORIGGPR2
11212d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) ((void) (state), 0)
11222d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg1(tcp, state, val) ((void) (state), 0)
11232d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_index	1
11242d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_index	0
11252d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(ALPHA) || defined(MIPS)
11262d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	REG_A0
11272d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(REG_A0+1)
11282d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(POWERPC)
11292d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(sizeof(unsigned long)*PT_R3)
11302d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(sizeof(unsigned long)*PT_R4)
11312d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) ((void) (state), 0)
11322d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(HPPA)
11332d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	PT_GR26
11342d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(PT_GR26-4)
113535be58119e3727a694d8c9f9b83f372401fcc4c0H.J. Lu# elif defined(X86_64) || defined(X32)
11362d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
11372d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
11382d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(SH)
11392d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(4*(REG_REG0+4))
11402d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(4*(REG_REG0+5))
11412d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(SH64)
11422d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko   /* ABI defines arg0 & 1 in r2 & r3 */
11432d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(REG_OFFSET+16)
11442d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(REG_OFFSET+24)
11452d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) 0
11462d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined CRISV10 || defined CRISV32
11472d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(4*PT_R11)
11482d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(4*PT_ORIG_R10)
11492d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) 0
11502d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg1(tcp, state, val) 0
11512d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_index	1
11522d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_index	0
11532d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# else
11542d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	0
11552d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	4
11562d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  if defined ARM
11572d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#   define restore_arg0(tcp, state, val) 0
11582d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  endif
11592d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# endif
1160d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1161d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1162d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11632d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_setup(tcp, state)         (0)
11642d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state) 0
11652d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg0(tcp, cookie, valp)   (upeek((tcp), arg0_offset, (valp)))
11662d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg1(tcp, cookie, valp)   (upeek((tcp), arg1_offset, (valp)))
1167d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1168d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
11691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, void *cookie, long val)
1170d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1171b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1172d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1173d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1174d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
11751201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, void *cookie, long val)
1176d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1177b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1178d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1179d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11802d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif /* architectures */
1181d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11822d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef restore_arg0
11832d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
11842d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
11852d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef restore_arg1
11862d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
11872d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
1188d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11892d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef arg0_index
11902d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg0_index 0
11912d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg1_index 1
11922d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
119390d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
119405eb905c4433c60d538e134619a3117522072a2fJames Hoganstatic int
119505eb905c4433c60d538e134619a3117522072a2fJames Hoganchange_syscall(struct tcb *tcp, arg_setup_state *state, int new)
119605eb905c4433c60d538e134619a3117522072a2fJames Hogan{
119705eb905c4433c60d538e134619a3117522072a2fJames Hogan#if defined(I386)
119805eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
119905eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
120005eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1201bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(X86_64)
120205eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
120305eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
120405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1205bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(X32)
1206bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* setbpt/clearbpt never used: */
1207bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* X32 is only supported since about linux-3.0.30 */
1208bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	return 0;
120905eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(POWERPC)
121005eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid,
121105eb905c4433c60d538e134619a3117522072a2fJames Hogan		   (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
121205eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
121305eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
121405eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(S390) || defined(S390X)
121505eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* s390 linux after 2.4.7 has a hook in entry.S to allow this */
121605eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
121705eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
121805eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
121905eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(M68K)
122005eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
122105eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
122205eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
122305eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SPARC) || defined(SPARC64)
122405eb905c4433c60d538e134619a3117522072a2fJames Hogan	state->u_regs[U_REG_G1] = new;
122505eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
122605eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(MIPS)
122705eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
122805eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
122905eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
123005eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(ALPHA)
123105eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
123205eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
123305eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
123405eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(AVR32)
1235d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1236d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* AVR32 is only supported since about linux-2.6.19 */
123705eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
123805eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(BFIN)
1239d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1240d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* Blackfin is only supported since about linux-2.6.23 */
124105eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
124205eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(IA64)
124305eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ia32) {
124405eb905c4433c60d538e134619a3117522072a2fJames Hogan		switch (new) {
124505eb905c4433c60d538e134619a3117522072a2fJames Hogan		case 2:
124605eb905c4433c60d538e134619a3117522072a2fJames Hogan			break;	/* x86 SYS_fork */
124705eb905c4433c60d538e134619a3117522072a2fJames Hogan		case SYS_clone:
124805eb905c4433c60d538e134619a3117522072a2fJames Hogan			new = 120;
124905eb905c4433c60d538e134619a3117522072a2fJames Hogan			break;
125005eb905c4433c60d538e134619a3117522072a2fJames Hogan		default:
125105eb905c4433c60d538e134619a3117522072a2fJames Hogan			fprintf(stderr, "%s: unexpected syscall %d\n",
125205eb905c4433c60d538e134619a3117522072a2fJames Hogan				__FUNCTION__, new);
125305eb905c4433c60d538e134619a3117522072a2fJames Hogan			return -1;
125405eb905c4433c60d538e134619a3117522072a2fJames Hogan		}
125505eb905c4433c60d538e134619a3117522072a2fJames Hogan		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
125605eb905c4433c60d538e134619a3117522072a2fJames Hogan			return -1;
125705eb905c4433c60d538e134619a3117522072a2fJames Hogan	} else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
125805eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
125905eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
126005eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(HPPA)
126105eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
126205eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
126305eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
126405eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SH)
126505eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
126605eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
126705eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
126805eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SH64)
126905eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* Top half of reg encodes the no. of args n as 0x1n.
127005eb905c4433c60d538e134619a3117522072a2fJames Hogan	   Assume 0 args as kernel never actually checks... */
127105eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
127205eb905c4433c60d538e134619a3117522072a2fJames Hogan				0x100000 | new) < 0)
127305eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
127405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
127505eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(CRISV10) || defined(CRISV32)
127605eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
127705eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
127805eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
127905eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(ARM)
128005eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* Some kernels support this, some (pre-2.6.16 or so) don't.  */
128105eb905c4433c60d538e134619a3117522072a2fJames Hogan# ifndef PTRACE_SET_SYSCALL
128205eb905c4433c60d538e134619a3117522072a2fJames Hogan#  define PTRACE_SET_SYSCALL 23
128305eb905c4433c60d538e134619a3117522072a2fJames Hogan# endif
128405eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
128505eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
128605eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1287bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(AARCH64)
1288bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* setbpt/clearbpt never used: */
1289bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* AARCH64 is only supported since about linux-3.0.31 */
1290bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	return 0;
129105eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(TILE)
1292d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1293d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* Tilera CPUs are only supported since about linux-2.6.34 */
129405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
129505eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(MICROBLAZE)
129605eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
129705eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
129805eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
129905eb905c4433c60d538e134619a3117522072a2fJames Hogan#else
130005eb905c4433c60d538e134619a3117522072a2fJames Hogan#warning Do not know how to handle change_syscall for this architecture
130105eb905c4433c60d538e134619a3117522072a2fJames Hogan#endif /* architecture */
130205eb905c4433c60d538e134619a3117522072a2fJames Hogan	return -1;
130305eb905c4433c60d538e134619a3117522072a2fJames Hogan}
130405eb905c4433c60d538e134619a3117522072a2fJames Hogan
1305d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1306418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkosetbpt(struct tcb *tcp)
1307d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
13083291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1309d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1310d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1311d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1312d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1313d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1314d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1315d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13163291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
13173291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
13183291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
13193291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
13203291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
13213291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
13223291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
13233291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
13243291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
13253291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
13263291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
13273291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
13283291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
13293291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
13300c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	if (sysent[tcp->scno].sys_func == sys_fork ||
13310c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	    sysent[tcp->scno].sys_func == sys_vfork) {
1332b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (arg_setup(tcp, &state) < 0
1333b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1334b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg1(tcp, &state, &tcp->inst[1]) < 0
133505eb905c4433c60d538e134619a3117522072a2fJames Hogan		    || change_syscall(tcp, &state,
133605eb905c4433c60d538e134619a3117522072a2fJames Hogan				      clone_scno[current_personality]) < 0
1337b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1338b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg1(tcp, &state, 0) < 0
1339b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || arg_finish_change(tcp, &state) < 0)
1340d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1341c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1342c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1343d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1344d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
13450c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	}
1346d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13470c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	if (sysent[tcp->scno].sys_func == sys_clone) {
13488fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
13490c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin		   contrary to x86 vfork above.  Even on x86 we turn the
13508fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
13518fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
13528fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
13538fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
13548fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
13558fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1356c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1357c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (new_arg0 & CLONE_VFORK)
1358c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1359c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (arg_setup(tcp, &state) < 0
1360c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || set_arg0(tcp, &state, new_arg0) < 0
1361c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || arg_finish_change(tcp, &state) < 0)
13625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			return -1;
1363c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1364c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
136555980f5b72000406e3fd843b098b5c1328a21e45Denys Vlasenko		tcp->flags |= TCB_BPTSET;
1366d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1367d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1368d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13690c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
13700c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin		tcp->scno, tcp->pid);
1371d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1372d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1373d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1374d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
13751201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
1376d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1377d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1378b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (arg_setup(tcp, &state) < 0
137905eb905c4433c60d538e134619a3117522072a2fJames Hogan	    || change_syscall(tcp, &state, tcp->scno) < 0
1380b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1381b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1382b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || arg_finish_change(tcp, &state))
1383c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (errno != ESRCH)
1384c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			return -1;
1385d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1386d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1387d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1388