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>
49faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#elif defined(HAVE_LINUX_PTRACE_H)
508470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko# undef PTRACE_SYSCALL
51ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_IA64_FPREG
52ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define ia64_fpreg XXX_ia64_fpreg
53ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
54ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
55ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath#  define pt_all_user_regs XXX_pt_all_user_regs
56ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# endif
570b4060f61f1bb101b5d8d084714b7d2feacdb199Ali Polatel# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
580b4060f61f1bb101b5d8d084714b7d2feacdb199Ali Polatel#  define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
590b4060f61f1bb101b5d8d084714b7d2feacdb199Ali Polatel# endif
608470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko# include <linux/ptrace.h>
610b4060f61f1bb101b5d8d084714b7d2feacdb199Ali Polatel# undef ptrace_peeksiginfo_args
62ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef ia64_fpreg
63ce9f0740d3b6e9910f25712771961bdb4bb4eaa2Roland McGrath# undef pt_all_user_regs
642e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman#endif
652e2553a534f532a1546ea2b2f3dc3cd2276d020dWichert Akkerman
6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
67ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstring_to_uint(const char *str)
68ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin{
69ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	char *error;
70ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	long value;
71ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
72ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	if (!*str)
73ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin		return -1;
74ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	errno = 0;
75ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	value = strtol(str, &error, 10);
76ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	if (errno || *error || value < 0 || (long)(int)value != value)
77ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin		return -1;
78ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	return (int)value;
79ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin}
80ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
81ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinint
82447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_nz(const struct timeval *a)
8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return a->tv_sec || a->tv_usec;
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
88447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_cmp(const struct timeval *a, const struct timeval *b)
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec < b->tv_sec
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (a->tv_sec > b->tv_sec
9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	    || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandouble
100447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_float(const struct timeval *tv)
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return tv->tv_sec + tv->tv_usec/1000000.0;
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
106447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec + b->tv_sec;
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec + b->tv_usec;
11058372f52ac5f824be687c01bfc1db1ffb963f91eRoland McGrath	if (tv->tv_usec >= 1000000) {
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec++;
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec -= 1000000;
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
117447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec - b->tv_sec;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec - b->tv_usec;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (((long) tv->tv_usec) < 0) {
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_sec--;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tv->tv_usec += 1000000;
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
128447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_div(struct timeval *tv, const struct timeval *a, int n)
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
136447db45365e37ec97c41b26b5a24e38d58e4f3aeDmitry V. Levintv_mul(struct timeval *tv, const struct timeval *a, int n)
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec = a->tv_usec * n;
139fefdd97156bb2f86c5b6596dc7e28d954516b3edDmitry V. Levin	tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tv->tv_usec %= 1000000;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinconst char *
144ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinxlookup(const struct xlat *xlat, int val)
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (; xlat->str != NULL; xlat++)
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val == val)
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return xlat->str;
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1520a295bc97fd2ba9e6dc02f382dc87bc8705dc4d0Denys Vlasenko#if !defined HAVE_STPCPY
1535284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenkochar *
1545284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenkostpcpy(char *dst, const char *src)
1555284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko{
1565284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	while ((*dst = *src++) != '\0')
1575284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko		dst++;
1585284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	return dst;
1595284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko}
1600a295bc97fd2ba9e6dc02f382dc87bc8705dc4d0Denys Vlasenko#endif
1615284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko
162b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko/* Find a next bit which is set.
163b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * Starts testing at cur_bit.
164b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * Returns -1 if no more bits are set.
165b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko *
166b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * We never touch bytes we don't need to.
167b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * On big-endian, array is assumed to consist of
168b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * current_wordsize wide words: for example, is current_wordsize is 4,
169b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
170b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko * On little-endian machines, word size is immaterial.
171b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko */
172b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenkoint
173b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenkonext_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
174b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko{
175b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	const unsigned endian = 1;
176b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	int little_endian = *(char*)&endian;
177b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko
178b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	const uint8_t *array = bit_array;
179b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	unsigned pos = cur_bit / 8;
180b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
181b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko
182b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	for (;;) {
183b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		uint8_t bitmask;
184b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		uint8_t cur_byte;
185b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko
186b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		if (cur_bit >= size_bits)
187b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			return -1;
188b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		cur_byte = array[pos ^ pos_xor_mask];
189b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		if (cur_byte == 0) {
190b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			cur_bit = (cur_bit + 8) & (-8);
191b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			pos++;
192b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			continue;
193b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		}
194b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		bitmask = 1 << (cur_bit & 7);
195b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		for (;;) {
196b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			if (cur_byte & bitmask)
197b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko				return cur_bit;
198b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			cur_bit++;
199b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			if (cur_bit >= size_bits)
200b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko				return -1;
201b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			bitmask <<= 1;
202b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			/* This check *can't be* optimized out: */
203b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko			if (bitmask == 0)
204b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko				break;
205b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		}
206b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko		pos++;
207b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko	}
208b338f2d65ea9d911a0fead3229ba336bc30e6214Denys Vlasenko}
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Print entry in struct xlat table, if there.
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
213ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levinprintxval(const struct xlat *xlat, int val, const char *dflt)
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
215ab9008bc085848e6c898cd38b7415baa161c5890Dmitry V. Levin	const char *str = xlookup(xlat, val);
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (str)
2185940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(str);
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#x /* %s */", val, dflt);
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
223b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab/*
224879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf * Print 64bit argument at position arg_no and return the index of the next
225b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab * argument.
226b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab */
227b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwabint
2287845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levinprintllval(struct tcb *tcp, const char *format, int arg_no, bool align)
229b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab{
2307a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
2317a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin# if SUPPORTED_PERSONALITIES > 1
2327a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin	if (current_wordsize > 4) {
2337a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin# endif
234879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf		tprintf(format, tcp->u_arg[arg_no]);
235879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf		arg_no++;
2367a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin# if SUPPORTED_PERSONALITIES > 1
237b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	} else {
2387a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#  if defined(AARCH64) || defined(POWERPC64)
2397845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin		if (align) {
2407845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin			/* Align arg_no to the next even number. */
2417845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin			arg_no = (arg_no + 1) & 0xe;
2427845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin		}
2437a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#  endif
244879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf		tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
245879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf		arg_no += 2;
246b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab	}
2477a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin# endif /* SUPPORTED_PERSONALITIES */
2487a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#elif SIZEOF_LONG > 4
2497a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#  error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
2507a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin#elif defined LINUX_MIPSN32
2517a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin	tprintf(format, tcp->ext_arg[arg_no]);
252879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf	arg_no++;
2530b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin#elif defined X32
2540b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin	if (current_personality == 0) {
2550b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin		tprintf(format, tcp->ext_arg[arg_no]);
2560b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin		arg_no++;
2570b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin	} else {
2580b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin		tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
2590b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin		arg_no += 2;
2600b468833390a78395be48f70d582a6679ab28a76Dmitry V. Levin	}
261c9d0fc0a63d5b425d6a4e9fedb4cb7a8e3129d6cDenys Vlasenko#else
2628e096c4ec507d9de1dd2f0d86ae925eb34b57053Dmitry V. Levin# if defined __ARM_EABI__ || \
2638e096c4ec507d9de1dd2f0d86ae925eb34b57053Dmitry V. Levin     defined LINUX_MIPSO32 || \
2648e096c4ec507d9de1dd2f0d86ae925eb34b57053Dmitry V. Levin     defined POWERPC || \
2658e096c4ec507d9de1dd2f0d86ae925eb34b57053Dmitry V. Levin     defined XTENSA
2667845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin	if (align) {
2677845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin		/* Align arg_no to the next even number. */
2687845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin		arg_no = (arg_no + 1) & 0xe;
2697845a42b39e59e904d01e75e21f7bc7eb6462560Dmitry V. Levin	}
2707a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin# endif
271879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf	tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
272879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf	arg_no += 2;
273c9d0fc0a63d5b425d6a4e9fedb4cb7a8e3129d6cDenys Vlasenko#endif
2747a498be266b80b7fef70fe74deed269ae3881525Dmitry V. Levin
275879ddddebab29211e495d99811cbd30a9eaf3055Chris Metcalf	return arg_no;
276b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab}
277b5600fc3df0453ba11f254a9b49add3ffbec9733Andreas Schwab
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interpret `xlat' as an array of flags
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * print the entries whose bits are on in `flags'
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * return # of flags printed.
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
2834924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenkovoid
2841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoaddflags(const struct xlat *xlat, int flags)
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2864924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko	for (; xlat->str; xlat++) {
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("|%s", xlat->str);
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags) {
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("|%#x", flags);
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
297a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath/*
2984924dbd6d750665cf383b20ab4fd67e48219ab91Denys Vlasenko * Interpret `xlat' as an array of flags.
299a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Print to static string the entries whose bits are on in `flags'
300a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath * Return static string.
301a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath */
302a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathconst char *
303a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrathsprintflags(const char *prefix, const struct xlat *xlat, int flags)
304a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath{
305a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	static char outstr[1024];
3065284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	char *outptr;
307a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	int found = 0;
308a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
3095284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko	outptr = stpcpy(outstr, prefix);
310a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
311a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	for (; xlat->str; xlat++) {
312a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if ((flags & xlat->val) == xlat->val) {
313a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			if (found)
3145284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko				*outptr++ = '|';
3155284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko			outptr = stpcpy(outptr, xlat->str);
316a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath			found = 1;
3174f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			flags &= ~xlat->val;
3184f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (!flags)
3194f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				break;
320a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		}
321a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
322a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	if (flags) {
323a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath		if (found)
3245284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko			*outptr++ = '|';
3255284557bfad96f12dd5798539008e1644f1dc094Denys Vlasenko		outptr += sprintf(outptr, "%#x", flags);
326a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	}
327a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
328a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath	return outstr;
329a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath}
330a6c0d8c90a1cc3117f70281968d9efe6de755d83Roland McGrath
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
33230145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintflags(const struct xlat *xlat, int flags, const char *dflt)
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
33530145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin	const char *sep;
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (flags == 0 && xlat->val == 0) {
3385940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(xlat->str);
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return 1;
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sep = "";
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (n = 0; xlat->str; xlat++) {
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (xlat->val && (flags & xlat->val) == xlat->val) {
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%s%s", sep, xlat->str);
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			flags &= ~xlat->val;
34776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sep = "|";
34876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			n++;
34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
351b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
352b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	if (n) {
353b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
354b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%s%#x", sep, flags);
355b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			n++;
356b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
357b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath	} else {
358b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		if (flags) {
359b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			tprintf("%#x", flags);
360b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
361b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath				tprintf(" /* %s */", dflt);
362b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		} else {
363b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath			if (dflt)
36460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko				tprints("0");
365b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath		}
36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
367b2dee13345a62c80a677f3342cd525d611fbc632Roland McGrath
36876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return n;
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
37230145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum(struct tcb *tcp, long addr, const char *fmt)
37376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
374eb285359906700f46b22cf4f9911695034313736Roland McGrath	long num;
37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
37760fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umove(tcp, addr, &num) < 0) {
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("[");
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf(fmt, num);
38660fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("]");
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3896bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrathvoid
39030145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinprintnum_int(struct tcb *tcp, long addr, const char *fmt)
3919814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath{
3929814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	int num;
3939814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
3949814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (!addr) {
39560fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
3969814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
3979814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
3989814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	if (umove(tcp, addr, &num) < 0) {
3999814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		tprintf("%#lx", addr);
4009814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath		return;
4019814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	}
40260fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("[");
4039814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath	tprintf(fmt, num);
40460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("]");
4059814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath}
4069814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrath
4079814a94bd10aea81b8bcb29e2ba167b09d70cedbRoland McGrathvoid
4083138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinprintfd(struct tcb *tcp, int fd)
4093138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin{
41061ad0a401c6d1b7b4c1a209f9d61c3790e1e7d15Denys Vlasenko	char path[PATH_MAX + 1];
4118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
41261ad0a401c6d1b7b4c1a209f9d61c3790e1e7d15Denys Vlasenko	if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
41361ad0a401c6d1b7b4c1a209f9d61c3790e1e7d15Denys Vlasenko		tprintf("%d<%s>", fd, path);
4148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards	else
4158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		tprintf("%d", fd);
4163138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin}
4173138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levin
4183138213bc9a827a372ad9f8009ebcc5d8797ce2dDmitry V. Levinvoid
4191201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintuid(const char *text, unsigned long uid)
4206bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath{
4215940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
4226bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath}
4236bc1220fe3f10e16919f182ad394c35619fe2e7fRoland McGrath
424a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
425a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Quote string `instr' of length `size'
426a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
427b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko * If `len' is -1, treat `instr' as a NUL-terminated string
428a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * and quote at most (`size' - 1) bytes.
4296cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
430b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
4316cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Note that if len >= 0, always returns 1.
432a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
433ebee04cfb009bdc46599774b4647f6615b6ce3a2Mike Frysingerint
434b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenkostring_quote(const char *instr, char *outstr, long len, int size)
43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
436bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	const unsigned char *ustr = (const unsigned char *) instr;
437bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	char *s = outstr;
4388778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	int usehex, c, i, eol;
43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
4408778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	eol = 0x100; /* this can never match a char */
441b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1) {
4428778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		size--;
4438778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		eol = '\0';
4448778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	}
4458778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
4468778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	usehex = 0;
447bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (xflag > 1)
448bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		usehex = 1;
449bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	else if (xflag) {
450a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Check for presence of symbol which require
451a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		   to hex-quote the whole string. */
452bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
453bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
454a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
4558778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
4568778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				break;
4575198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko
4585198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			/* Force hex unless c is printable or whitespace */
4595198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			if (c > 0x7e) {
4605198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko				usehex = 1;
4615198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko				break;
4625198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			}
4635198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			/* In ASCII isspace is only these chars: "\t\n\v\f\r".
4645198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			 * They happen to have ASCII codes 9,10,11,12,13.
4655198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			 */
4665198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko			if (c < ' ' && (unsigned)(c - 9) >= 5) {
467bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				usehex = 1;
468bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				break;
469bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
470bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
472bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
473bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
474bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
475bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	if (usehex) {
476a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/* Hex-quote the whole string. */
477bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
478bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
479a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
4808778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
4818778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				goto asciz_ended;
4828778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = '\\';
4838778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = 'x';
4848778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = "0123456789abcdef"[c >> 4];
4858778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			*s++ = "0123456789abcdef"[c & 0xf];
486bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		}
487bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	} else {
488bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		for (i = 0; i < size; ++i) {
489bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			c = ustr[i];
490a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin			/* Check for NUL-terminated string. */
4918778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko			if (c == eol)
4928778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko				goto asciz_ended;
493bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			switch (c) {
494bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\"': case '\\':
495bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
496bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = c;
497bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
498bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\f':
499bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
500bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'f';
501bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
502bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\n':
503bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
504bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'n';
505bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
506bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\r':
507bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
508bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'r';
509bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
510bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\t':
511bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
512bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 't';
513bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
514bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				case '\v':
515bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = '\\';
516bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					*s++ = 'v';
517bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
518bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin				default:
5195198ed4bb36e3105a1f12bb3250bee78b6e0dd72Denys Vlasenko					if (c >= ' ' && c <= 0x7e)
520bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin						*s++ = c;
5218778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko					else {
5228778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						/* Print \octal */
5238778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						*s++ = '\\';
5248778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						if (i + 1 < size
5258778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						    && ustr[i + 1] >= '0'
5268778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						    && ustr[i + 1] <= '9'
5278778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						) {
5288778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							/* Print \ooo */
5298778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							*s++ = '0' + (c >> 6);
5308778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							*s++ = '0' + ((c >> 3) & 0x7);
5318778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						} else {
5328778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							/* Print \[[o]o]o */
5338778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							if ((c >> 3) != 0) {
5348778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko								if ((c >> 6) != 0)
5358778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko									*s++ = '0' + (c >> 6);
5368778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko								*s++ = '0' + ((c >> 3) & 0x7);
5378778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko							}
5388778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						}
5398778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko						*s++ = '0' + (c & 0x7);
540bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					}
541bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin					break;
542bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin			}
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
546bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s++ = '\"';
547bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	*s = '\0';
5486d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath
5498778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	/* Return zero if we printed entire ASCIZ string (didn't truncate it) */
550b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1 && ustr[i] == '\0') {
5518778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		/* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
5528778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		 * but next char is NUL.
5538778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		 */
5548778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko		return 0;
5558778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	}
5568778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
5578778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	return 1;
5588778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko
5598778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko asciz_ended:
5608778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	*s++ = '\"';
5618778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	*s = '\0';
5628778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	/* Return zero: we printed entire ASCIZ string (didn't truncate it) */
5638778bffdd25dca050b3aa2a7a7e05bc8a63a6665Denys Vlasenko	return 0;
56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
566a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
567a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print path string specified by address `addr' and length `n'.
568a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If path length exceeds `n', append `...' to the output.
569a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
571bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpathn(struct tcb *tcp, long addr, int n)
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
573b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	char path[MAXPATHLEN + 1];
5746cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	int nul_seen;
575b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko
576a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (!addr) {
57760fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
578bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		return;
579bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	}
580bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
5816cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	/* Cap path length to the path buffer size */
582a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	if (n > sizeof path - 1)
583a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		n = sizeof path - 1;
584a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin
585a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Fetch one byte more to find out whether path length > n. */
5866cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	nul_seen = umovestr(tcp, addr, n + 1, path);
5876cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	if (nul_seen < 0)
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%#lx", addr);
58976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
590b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		char *outstr;
591bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
5926cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		path[n] = '\0';
593b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		n++;
5946cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
595b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		string_quote(path, outstr, -1, n);
596b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		tprints(outstr);
5976cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko		if (!nul_seen)
598b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko			tprints("...");
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
60076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
603bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinprintpath(struct tcb *tcp, long addr)
604bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin{
605b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	/* Size must correspond to char path[] size in printpathn */
606b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	printpathn(tcp, addr, MAXPATHLEN);
607bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin}
608bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
609a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin/*
610a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * Print string specified by address `addr' and length `len'.
611a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If `len' < 0, treat the string as a NUL-terminated string.
612a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin * If string length exceeds `max_strlen', append `...' to the output.
613a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin */
614bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levinvoid
615b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenkoprintstr(struct tcb *tcp, long addr, long len)
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
617bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin	static char *str = NULL;
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char *outstr;
6196d9703205e06c77c6c8d38eac6796cfc9a4ea92cRoland McGrath	int size;
620b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	int ellipsis;
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!addr) {
62360fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko		tprints("NULL");
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
626a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin	/* Allocate static buffers if they are not allocated yet. */
6271d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!str) {
628378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
629378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin
630378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		if (outstr_size / 4 != max_strlen)
631378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin			die_out_of_memory();
632a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		str = malloc(max_strlen + 1);
6331d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		if (!str)
6341d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			die_out_of_memory();
635378f9c5ad0043632475cd17cbe5fe4cf38971b2bDmitry V. Levin		outstr = malloc(outstr_size);
6361d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		if (!outstr)
6371d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			die_out_of_memory();
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
639bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin
640b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko	if (len == -1) {
641a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		/*
642a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * Treat as a NUL-terminated string: fetch one byte more
643a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 * because string_quote() quotes one byte less.
644a501f1426eeeeeb6fc31317c1ab7cc491026f495Dmitry V. Levin		 */
645bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		size = max_strlen + 1;
646bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umovestr(tcp, addr, size, str) < 0) {
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
652b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko		size = max_strlen;
653b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko		if (size > (unsigned long)len)
654b5d43b81a8abdf17bc3aa585a66215ebe3ba3671Denys Vlasenko			size = (unsigned long)len;
655bea0203d2d4c8be1818c7d93a630306d79edf716Dmitry V. Levin		if (umoven(tcp, addr, size, str) < 0) {
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%#lx", addr);
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6616cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	/* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
6626cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	 * or we were requested to print more than -s NUM chars)...
6636cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko	 */
664b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	ellipsis = (string_quote(str, outstr, len, size) &&
665b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko			(len < 0 || len > max_strlen));
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
667b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	tprints(outstr);
668b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko	if (ellipsis)
669b3c52cf02ae536634898cd12afa5f3fcad17fbf2Denys Vlasenko		tprints("...");
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6721d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#if HAVE_SYS_UIO_H
6731d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughesvoid
6741201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpiov(struct tcb *tcp, int len, long addr)
6751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes{
6768470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1
6774ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	union {
6784ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int32_t base; u_int32_t len; } *iov32;
6794ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin		struct { u_int64_t base; u_int64_t len; } *iov64;
6804ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	} iovu;
6814ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov iovu.iov64
6824ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov \
6839fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
6844ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) \
6859fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
6864ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) \
6879fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
6884ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#else
6891d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	struct iovec *iov;
6904ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define sizeof_iov sizeof(*iov)
6914ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_base(i) iov[i].iov_base
6924ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#define iov_iov_len(i) iov[i].iov_len
6934ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#endif
6941d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	int i;
69579a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	unsigned size;
6961d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
69779a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	size = sizeof_iov * len;
69879a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	/* Assuming no sane program has millions of iovs */
69979a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	if ((unsigned)len > 1024*1024 /* insane or negative size? */
7004ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin	    || (iov = malloc(size)) == NULL) {
70179a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		fprintf(stderr, "Out of memory\n");
70279a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		return;
7031d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
704aa524c88c49814863cb7f19e5c8a8eeca6ce22feRoland McGrath	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
7051d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes		for (i = 0; i < len; i++) {
706adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			/* include the buffer number to make it easy to
707adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			 * match up the trace with the source */
708adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			tprintf(" * %lu bytes in buffer %d\n",
709adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				(unsigned long)iov_iov_len(i), i);
710adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko			dumpstr(tcp, (long) iov_iov_base(i),
711adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko				iov_iov_len(i));
712adedb510197209e7077310f9e9f67e3d51fb8617Denys Vlasenko		}
7131d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes	}
71479a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko	free(iov);
7154ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef sizeof_iov
7164ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_base
7174ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov_iov_len
7184ebb4e3d312bb8215f4eea9130cce6bb8bdb972fDmitry V. Levin#undef iov
7191d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes}
7201d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
7211d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
7231201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodumpstr(struct tcb *tcp, long addr, int len)
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int strsize = -1;
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static unsigned char *str;
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
728763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	char outbuf[
729763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		(
730763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			(sizeof(
731763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			"xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx  "
732763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			"1234567890123456") + /*in case I'm off by few:*/ 4)
733763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		/*align to 8 to make memset easier:*/ + 7) & -8
734763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	];
735763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	const unsigned char *src;
736763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	int i;
737763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko
738763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	memset(outbuf, ' ', sizeof(outbuf));
739763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko
740763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	if (strsize < len + 16) {
7415d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		free(str);
742763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		str = malloc(len + 16);
74379a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		if (!str) {
74479a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			strsize = -1;
74579a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			fprintf(stderr, "Out of memory\n");
74679a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko			return;
74779a79ea851250a30005d6323b20a9e30d9f336c1Denys Vlasenko		}
748763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		strsize = len + 16;
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (umoven(tcp, addr, len, (char *) str) < 0)
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
754763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	/* Space-pad to 16 bytes */
755763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	i = len;
756763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	while (i & 0xf)
757763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		str[i++] = ' ';
758763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko
759763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	i = 0;
760763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	src = str;
761763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko	while (i < len) {
762763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		char *dst = outbuf;
763763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		/* Hex dump */
764763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		do {
765763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			if (i < len) {
766763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = "0123456789abcdef"[*src >> 4];
767763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = "0123456789abcdef"[*src & 0xf];
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
770763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = ' ';
771763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = ' ';
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
773763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			dst++; /* space is there by memset */
774763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			i++;
775763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			if ((i & 7) == 0)
776763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				dst++; /* space is there by memset */
777763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			src++;
778763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		} while (i & 0xf);
779763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		/* ASCII dump */
780763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		i -= 16;
781763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		src -= 16;
782763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		do {
783763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			if (*src >= ' ' && *src < 0x7f)
784763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = *src;
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
786763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko				*dst++ = '.';
787763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko			src++;
788763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		} while (++i & 0xf);
789763258071ccafd3499979348a5461670bbe20bd8Denys Vlasenko		*dst = '\0';
790f90979b7014b6b158eed6105b1bdf6014cea70f6Denys Vlasenko		tprintf(" | %05x  %s |\n", i - 16, outbuf);
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
794612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#ifdef HAVE_PROCESS_VM_READV
795612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger/* C library supports this, but the kernel might not. */
796612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysingerstatic bool process_vm_readv_not_supported = 0;
797612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#else
798612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger
7993af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko/* Need to do this since process_vm_readv() is not yet available in libc.
8003af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko * When libc is be updated, only "static bool process_vm_readv_not_supported"
8013af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko * line should remain.
8023af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko */
8033af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#if !defined(__NR_process_vm_readv)
8043af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# if defined(I386)
8053af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  347
8063af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# elif defined(X86_64)
8073af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  310
8083af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# elif defined(POWERPC)
8093af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#  define __NR_process_vm_readv  351
8103af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# endif
8113af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#endif
8123af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8133af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#if defined(__NR_process_vm_readv)
8143af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenkostatic bool process_vm_readv_not_supported = 0;
81524ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysinger/* Have to avoid duplicating with the C library headers. */
81624ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysingerstatic ssize_t strace_process_vm_readv(pid_t pid,
8173af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 const struct iovec *lvec,
8183af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long liovcnt,
8193af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 const struct iovec *rvec,
8203af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long riovcnt,
8213af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		 unsigned long flags)
8223af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko{
8233af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
8243af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko}
82524ee60b836ad33bb4ac694ca99d6c94a8cc5ff92Mike Frysinger#define process_vm_readv strace_process_vm_readv
8263af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#else
8273af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenkostatic bool process_vm_readv_not_supported = 1;
8283af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko# define process_vm_readv(...) (errno = ENOSYS, -1)
8293af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko#endif
830612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger
831612659e41e2f41490ea5ae2926f5e002bb398334Mike Frysinger#endif /* end of hack */
8323af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define PAGMASK	(~(PAGSIZ - 1))
83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * move `len' bytes of data from process `pid'
83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * at address `addr' to our space at `laddr'
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
839ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumoven(struct tcb *tcp, long addr, int len, char *laddr)
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
841eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
8429700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin	int n, m, nread;
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		long val;
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8482544f988c96a48e48369a767d8886c4282859ed3Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
8499fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	if (current_wordsize < sizeof(addr))
8509fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko		addr &= (1ul << 8 * current_wordsize) - 1;
851d2a660f534d98169f60d50706cbb2ec15fa13cf8Denys Vlasenko#endif
852d2a660f534d98169f60d50706cbb2ec15fa13cf8Denys Vlasenko
8533af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	if (!process_vm_readv_not_supported) {
8543af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		struct iovec local[1], remote[1];
8553af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		int r;
8563af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8573af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_base = laddr;
8583af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		remote[0].iov_base = (void*)addr;
8593af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_len = remote[0].iov_len = len;
8609700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		r = process_vm_readv(pid, local, 1, remote, 1, 0);
8611d58fe9b3b925735bde72cac96a042b3cef03037Ben Noordhuis		if (r == len)
8621d58fe9b3b925735bde72cac96a042b3cef03037Ben Noordhuis			return 0;
8639700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		if (r >= 0) {
8649700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			error_msg("umoven: short read (%d < %d) @0x%lx",
8659700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				  r, len, addr);
8669700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			return -1;
8679700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		}
8689700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		switch (errno) {
8699700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ENOSYS:
8703af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				process_vm_readv_not_supported = 1;
8719700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				break;
8729700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ESRCH:
8739700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* the process is gone */
8749700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
8759700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case EFAULT: case EIO: case EPERM:
8769700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* address space is inaccessible */
8779700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
8789700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			default:
8799700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* all the rest is strange and should be reported */
880905e8e0e2f0a1f51ab92424dcb005885ea8b2459Denys Vlasenko				perror_msg("process_vm_readv");
8819700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
8823af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		}
8833af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	}
8843af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
8859700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin	nread = 0;
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
890eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
891eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
8929700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		switch (errno) {
8939700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case 0:
8949700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				break;
8959700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ESRCH: case EINVAL:
8969700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* these could be seen if the process is gone */
8979700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
8989700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case EFAULT: case EIO: case EPERM:
8999700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* address space is inaccessible */
9009700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
9019700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			default:
9029700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* all the rest is strange and should be reported */
9039700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
9049700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					    pid, addr);
9059700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
906eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
907a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long) - n, len);
908a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, &u.x[n], m);
9091694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		addr += sizeof(long);
9101694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		laddr += m;
9111694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		nread += m;
9121694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		len -= m;
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
915eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
916eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
9179700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		switch (errno) {
9189700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case 0:
9199700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				break;
9209700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ESRCH: case EINVAL:
9219700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* these could be seen if the process is gone */
9229700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
9239700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case EFAULT: case EIO: case EPERM:
9249700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* address space is inaccessible */
9259700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				if (nread) {
9269700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					perror_msg("umoven: short read (%d < %d) @0x%lx",
9279700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin						   nread, nread + len, addr - nread);
9289700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				}
9299700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
9309700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			default:
9319700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* all the rest is strange and should be reported */
9329700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
9339700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					    pid, addr);
9349700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
935eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
936a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long), len);
937a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, u.x, m);
9381694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		addr += sizeof(long);
9391694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		laddr += m;
9401694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		nread += m;
9411694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		len -= m;
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
9486cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Like `umove' but make the additional effort of looking
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * for a terminating zero byte.
9506cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
9516cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Returns < 0 on error, > 0 if NUL was seen,
9526cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * (TODO if useful: return count of bytes including NUL),
9536cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * else 0 if len bytes were read but no NUL byte seen.
9546cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko *
9556cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * Note: there is no guarantee we won't overwrite some bytes
9566cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * in laddr[] _after_ terminating NUL (but, of course,
9576cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko * we never write past laddr[len-1]).
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
960ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoumovestr(struct tcb *tcp, long addr, int len, char *laddr)
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
9621694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko#if SIZEOF_LONG == 4
9631694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko	const unsigned long x01010101 = 0x01010101ul;
9641694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko	const unsigned long x80808080 = 0x80808080ul;
9651694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko#elif SIZEOF_LONG == 8
9661694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko	const unsigned long x01010101 = 0x0101010101010101ul;
9671694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko	const unsigned long x80808080 = 0x8080808080808080ul;
9681694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko#else
9691694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko# error SIZEOF_LONG > 8
9701694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko#endif
9711694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko
972eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	int pid = tcp->pid;
9731694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko	int n, m, nread;
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	union {
9751694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		unsigned long val;
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char x[sizeof(long)];
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	} u;
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9792544f988c96a48e48369a767d8886c4282859ed3Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
9809fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko	if (current_wordsize < sizeof(addr))
9819fd4f96d2a2527ac7ca90c156bfc11ce10118684Denys Vlasenko		addr &= (1ul << 8 * current_wordsize) - 1;
982856c7ed97bce524ade99bb1fc41e746973d45accDmitry V. Levin#endif
983856c7ed97bce524ade99bb1fc41e746973d45accDmitry V. Levin
9849700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin	nread = 0;
9853af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	if (!process_vm_readv_not_supported) {
9863af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		struct iovec local[1], remote[1];
9873af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
9883af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		local[0].iov_base = laddr;
9893af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		remote[0].iov_base = (void*)addr;
9903af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
9913af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		while (len > 0) {
9923af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int end_in_page;
9933af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int r;
9943af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			int chunk_len;
9953af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
9963af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			/* Don't read kilobytes: most strings are short */
9973af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			chunk_len = len;
9983af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (chunk_len > 256)
9993af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				chunk_len = 256;
10003af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			/* Don't cross pages. I guess otherwise we can get EFAULT
10013af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * and fail to notice that terminating NUL lies
10023af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * in the existing (first) page.
10033af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 * (I hope there aren't arches with pages < 4K)
10043af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			 */
10053af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			end_in_page = ((addr + chunk_len) & 4095);
10063af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			r = chunk_len - end_in_page;
10073af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			if (r > 0) /* if chunk_len > end_in_page */
10083af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko				chunk_len = r; /* chunk_len -= end_in_page */
10093af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
10103af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			local[0].iov_len = remote[0].iov_len = chunk_len;
10119700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			r = process_vm_readv(pid, local, 1, remote, 1, 0);
10129700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			if (r > 0) {
10139700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				if (memchr(local[0].iov_base, '\0', r))
10149700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					return 1;
10159700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				local[0].iov_base += r;
10169700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				remote[0].iov_base += r;
10179700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				len -= r;
10189700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				nread += r;
10199700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				continue;
10209700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			}
10219700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			switch (errno) {
10229700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				case ENOSYS:
10233af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko					process_vm_readv_not_supported = 1;
10249700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					goto vm_readv_didnt_work;
10259700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				case ESRCH:
10269700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					/* the process is gone */
10279700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					return -1;
10289700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				case EFAULT: case EIO: case EPERM:
10299700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					/* address space is inaccessible */
10309700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					if (nread) {
10319700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin						perror_msg("umovestr: short read (%d < %d) @0x%lx",
10329700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin							   nread, nread + len, addr);
10339700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					}
10349700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					return -1;
10359700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				default:
10369700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					/* all the rest is strange and should be reported */
1037905e8e0e2f0a1f51ab92424dcb005885ea8b2459Denys Vlasenko					perror_msg("process_vm_readv");
10389700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					return -1;
10393af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko			}
10403af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		}
10413af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko		return 0;
10423af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko	}
10433af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko vm_readv_didnt_work:
10443af224c5cd8a64a6af3f875549ff821e2b5cb211Denys Vlasenko
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (addr & (sizeof(long) - 1)) {
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* addr not a multiple of sizeof(long) */
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		n = addr - (addr & -sizeof(long)); /* residue */
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		addr &= -sizeof(long); /* residue */
1049eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
1050eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
10519700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		switch (errno) {
10529700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case 0:
10539700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				break;
10549700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ESRCH: case EINVAL:
10559700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* these could be seen if the process is gone */
10569700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
10579700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case EFAULT: case EIO: case EPERM:
10589700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* address space is inaccessible */
10599700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
10609700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			default:
10619700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* all the rest is strange and should be reported */
10629700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
10639700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					    pid, addr);
10649700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
1065eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
1066a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long) - n, len);
1067a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, &u.x[n], m);
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		while (n & (sizeof(long) - 1))
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (u.x[n++] == '\0')
10706cecba53225ae30f1a28ce6954fb0cda847f3688Denys Vlasenko				return 1;
10711694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		addr += sizeof(long);
10721694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		laddr += m;
10731694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		nread += m;
10741694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		len -= m;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
10761694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (len) {
1078eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		errno = 0;
1079eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
10809700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin		switch (errno) {
10819700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case 0:
10829700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				break;
10839700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case ESRCH: case EINVAL:
10849700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* these could be seen if the process is gone */
10859700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
10869700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			case EFAULT: case EIO: case EPERM:
10879700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* address space is inaccessible */
10889700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				if (nread) {
10899700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					perror_msg("umovestr: short read (%d < %d) @0x%lx",
10909700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin						   nread, nread + len, addr - nread);
10919700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				}
10929700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
10939700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin			default:
10949700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				/* all the rest is strange and should be reported */
10959700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
10969700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin					   pid, addr);
10979700592e49bd7407c58693f1d397055fa485fc18Dmitry V. Levin				return -1;
1098eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
1099a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		m = MIN(sizeof(long), len);
1100a47e6b9fbb98e2363af28cf9cfa436964faa4fc6Denys Vlasenko		memcpy(laddr, u.x, m);
11011694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		/* "If a NUL char exists in this word" */
11021694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		if ((u.val - x01010101) & ~u.val & x80808080)
11031694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko			return 1;
11041694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		addr += sizeof(long);
11051694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		laddr += m;
11061694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		nread += m;
11071694092d7d92953dbee0639ead0ae379f145c4ddDenys Vlasenko		len -= m;
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1109aa09c6b01ee425d419cdae4389fad0a06da489efJohn Hughes	return 0;
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1113752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenkoupeek(int pid, long off, long *res)
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long val;
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1117eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1118752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko	val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
1119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	if (val == -1 && errno) {
1120eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (errno != ESRCH) {
1121752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko			perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
1122eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		}
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
1124eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	}
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	*res = val;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1129d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1130d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * and PTRACE_O_TRACE[V]FORK for tracing children.
1131d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * If you are adding a new arch which is only supported by newer kernels,
1132d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * you most likely don't need to add any code below
1133d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko * beside a dummy "return 0" block in change_syscall().
1134d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko */
1135d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko
11363bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko/*
11373bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * These #if's are huge, please indent them correctly.
11383bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko * It's easy to get confused otherwise.
11393bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko */
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11412d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#include "syscall.h"
11423291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
11432d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_PTRACE
11442d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_PTRACE    0x00002000
11452d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
11462d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_VFORK
11472d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_VFORK     0x00004000
11482d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
11492d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef CLONE_VM
11502d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define CLONE_VM        0x00000100
11512d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
1152d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11532d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifdef IA64
1154d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1155d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef unsigned long *arg_setup_state;
1156d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1157d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
1158d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGratharg_setup(struct tcb *tcp, arg_setup_state *state)
1159d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
11601f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	unsigned long cfm, sof, sol;
11611f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	long bsp;
1162d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1163c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode) {
11641f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		/* Satisfy a false GCC warning.  */
11651f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil		*state = NULL;
116608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		return 0;
11671f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	}
116808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1169752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko	if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
1170d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1171752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko	if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1172d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1173d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1174d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sof = (cfm >> 0) & 0x7f;
1175d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	sol = (cfm >> 7) & 0x7f;
11761f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1177d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11781f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil	*state = (unsigned long *) bsp;
1179d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1180d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1181d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
11822d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state)	0
1183d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1184d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
11851201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1186d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
118708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
118808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1189c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode)
1190752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko		ret = upeek(tcp->pid, PT_R11, valp);
119108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1192b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
119308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 0),
119408267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
119508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1196d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1197d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1198d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
11991201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoget_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1200d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
120108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int ret;
120208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1203c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode)
1204752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko		ret = upeek(tcp->pid, PT_R9, valp);
120508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	else
1206b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		ret = umoven(tcp,
120708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      (unsigned long) ia64_rse_skip_regs(*state, 1),
120808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath			      sizeof(long), (void *) valp);
120908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	return ret;
1210d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1211d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1212d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12131201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1214d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
121508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
121608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
121708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1218c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode) {
121908267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R11;	 /* r11 == EBX */
122008267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
122108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
122208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 0);
1223eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1224eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1225eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1226d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1227d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1228d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
12291201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1230d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
123108267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	int req = PTRACE_POKEDATA;
123208267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	void *ap;
123308267b8d6703c23332e39b1296e10e327196acb3Roland McGrath
1234c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode) {
123508267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = (void *) (intptr_t) PT_R9;		/* r9 == ECX */
123608267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		req = PTRACE_POKEUSER;
123708267b8d6703c23332e39b1296e10e327196acb3Roland McGrath	} else
123808267b8d6703c23332e39b1296e10e327196acb3Roland McGrath		ap = ia64_rse_skip_regs(*state, 1);
1239eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	errno = 0;
1240eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	ptrace(req, tcp->pid, ap, val);
1241eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	return errno ? -1 : 0;
1242d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1243d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1244b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath/* ia64 does not return the input arguments from functions (and syscalls)
1245b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath   according to ia64 RSE (Register Stack Engine) behavior.  */
1246b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
12472d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) ((void) (state), 0)
12482d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg1(tcp, state, val) ((void) (state), 0)
1249b659f87e7d5b10f2c06626368efb8a0637f91da5Roland McGrath
12502d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#elif defined(SPARC) || defined(SPARC64)
1251d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1252ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko# if defined(SPARC64)
1253ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  undef PTRACE_GETREGS
1254ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  define PTRACE_GETREGS PTRACE_GETREGS64
1255ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  undef PTRACE_SETREGS
1256ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko#  define PTRACE_SETREGS PTRACE_SETREGS64
1257ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko# endif
1258ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko
12598566c500253f3bef38ace7d6031f76fe5d21f7e0Mike Frysingertypedef struct pt_regs arg_setup_state;
1260d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12612d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_setup(tcp, state) \
12622d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko    (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
12632d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state) \
12642d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko    (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
1265d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12662d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
12672d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
12682d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define set_arg0(tcp, state, val)  ((state)->u_regs[U_REG_O0] = (val), 0)
12692d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define set_arg1(tcp, state, val)  ((state)->u_regs[U_REG_O1] = (val), 0)
12702d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) 0
1271d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12722d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#else /* other architectures */
1273d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
12742d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# if defined S390 || defined S390X
12757b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath/* Note: this is only true for the `clone' system call, which handles
12767b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   arguments specially.  We could as well say that its first two arguments
12777b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   are swapped relative to other architectures, but that would just be
12787b3082206c5ea5ea41259c8b013138c6f6b6463aRoland McGrath   another #ifdef in the calls.  */
12792d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	PT_GPR3
12802d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	PT_ORIGGPR2
12812d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) ((void) (state), 0)
12822d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg1(tcp, state, val) ((void) (state), 0)
12832d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_index	1
12842d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_index	0
12852d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(ALPHA) || defined(MIPS)
12862d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	REG_A0
12872d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(REG_A0+1)
12882d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(POWERPC)
12892d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(sizeof(unsigned long)*PT_R3)
12902d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(sizeof(unsigned long)*PT_R4)
12912d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) ((void) (state), 0)
12922d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(HPPA)
12932d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	PT_GR26
12942d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(PT_GR26-4)
129535be58119e3727a694d8c9f9b83f372401fcc4c0H.J. Lu# elif defined(X86_64) || defined(X32)
12962d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	((long)(8*(current_personality ? RBX : RDI)))
12972d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	((long)(8*(current_personality ? RCX : RSI)))
12982d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(SH)
12992d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(4*(REG_REG0+4))
13002d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(4*(REG_REG0+5))
13012d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined(SH64)
13022d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko   /* ABI defines arg0 & 1 in r2 & r3 */
13032d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(REG_OFFSET+16)
13042d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(REG_OFFSET+24)
13052d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) 0
13062d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# elif defined CRISV10 || defined CRISV32
13072d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	(4*PT_R11)
13082d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	(4*PT_ORIG_R10)
13092d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg0(tcp, state, val) 0
13102d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define restore_arg1(tcp, state, val) 0
13112d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_index	1
13122d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_index	0
13132d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# else
13142d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg0_offset	0
13152d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  define arg1_offset	4
13162d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  if defined ARM
13172d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#   define restore_arg0(tcp, state, val) 0
13182d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#  endif
13192d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# endif
1320d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1321d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathtypedef int arg_setup_state;
1322d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13232d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_setup(tcp, state)         (0)
13242d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg_finish_change(tcp, state) 0
1325752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko# define get_arg0(tcp, cookie, valp)   (upeek((tcp)->pid, arg0_offset, (valp)))
1326752e5a02e67f66f555aa39faf522f07126924e62Denys Vlasenko# define get_arg1(tcp, cookie, valp)   (upeek((tcp)->pid, arg1_offset, (valp)))
1327d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1328d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13291201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg0(struct tcb *tcp, void *cookie, long val)
1330d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1331b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1332d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1333d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1334d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathstatic int
13351201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoset_arg1(struct tcb *tcp, void *cookie, long val)
1336d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1337b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1338d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1339d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13402d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif /* architectures */
1341d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13422d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef restore_arg0
13432d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
13442d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
13452d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef restore_arg1
13462d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
13472d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
1348d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
13492d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#ifndef arg0_index
13502d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg0_index 0
13512d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko# define arg1_index 1
13522d1e90f9588281bb5520783006c06bc23f997bf8Denys Vlasenko#endif
135390d0afd72811fa149d66b9c6b59d0ebcbf9aba6bRoland McGrath
135405eb905c4433c60d538e134619a3117522072a2fJames Hoganstatic int
135505eb905c4433c60d538e134619a3117522072a2fJames Hoganchange_syscall(struct tcb *tcp, arg_setup_state *state, int new)
135605eb905c4433c60d538e134619a3117522072a2fJames Hogan{
135705eb905c4433c60d538e134619a3117522072a2fJames Hogan#if defined(I386)
135805eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
135905eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
136005eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1361bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(X86_64)
136205eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
136305eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
136405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1365bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(X32)
1366bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* setbpt/clearbpt never used: */
1367bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* X32 is only supported since about linux-3.0.30 */
136805eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(POWERPC)
136905eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid,
137005eb905c4433c60d538e134619a3117522072a2fJames Hogan		   (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
137105eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
137205eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
137305eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(S390) || defined(S390X)
137405eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* s390 linux after 2.4.7 has a hook in entry.S to allow this */
137505eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
137605eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
137705eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
137805eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(M68K)
137905eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
138005eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
138105eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
138205eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SPARC) || defined(SPARC64)
138305eb905c4433c60d538e134619a3117522072a2fJames Hogan	state->u_regs[U_REG_G1] = new;
138405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
138505eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(MIPS)
138605eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
138705eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
138805eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
138905eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(ALPHA)
139005eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
139105eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
139205eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
139305eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(AVR32)
1394d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1395d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* AVR32 is only supported since about linux-2.6.19 */
139605eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(BFIN)
1397d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1398d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* Blackfin is only supported since about linux-2.6.23 */
139905eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(IA64)
1400c09646aa9e8768d308267bb92747b2d1ff58b1c3Denys Vlasenko	if (ia64_ia32mode) {
140105eb905c4433c60d538e134619a3117522072a2fJames Hogan		switch (new) {
140205eb905c4433c60d538e134619a3117522072a2fJames Hogan		case 2:
140305eb905c4433c60d538e134619a3117522072a2fJames Hogan			break;	/* x86 SYS_fork */
140405eb905c4433c60d538e134619a3117522072a2fJames Hogan		case SYS_clone:
140505eb905c4433c60d538e134619a3117522072a2fJames Hogan			new = 120;
140605eb905c4433c60d538e134619a3117522072a2fJames Hogan			break;
140705eb905c4433c60d538e134619a3117522072a2fJames Hogan		default:
140805eb905c4433c60d538e134619a3117522072a2fJames Hogan			fprintf(stderr, "%s: unexpected syscall %d\n",
140905eb905c4433c60d538e134619a3117522072a2fJames Hogan				__FUNCTION__, new);
141005eb905c4433c60d538e134619a3117522072a2fJames Hogan			return -1;
141105eb905c4433c60d538e134619a3117522072a2fJames Hogan		}
141205eb905c4433c60d538e134619a3117522072a2fJames Hogan		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
141305eb905c4433c60d538e134619a3117522072a2fJames Hogan			return -1;
141405eb905c4433c60d538e134619a3117522072a2fJames Hogan	} else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
141505eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
141605eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
141705eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(HPPA)
141805eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
141905eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
142005eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
142105eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SH)
142205eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
142305eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
142405eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
142505eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(SH64)
142605eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* Top half of reg encodes the no. of args n as 0x1n.
142705eb905c4433c60d538e134619a3117522072a2fJames Hogan	   Assume 0 args as kernel never actually checks... */
142805eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
142905eb905c4433c60d538e134619a3117522072a2fJames Hogan				0x100000 | new) < 0)
143005eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
143105eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
143205eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(CRISV10) || defined(CRISV32)
143305eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
143405eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
143505eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
143605eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(ARM)
143705eb905c4433c60d538e134619a3117522072a2fJames Hogan	/* Some kernels support this, some (pre-2.6.16 or so) don't.  */
143805eb905c4433c60d538e134619a3117522072a2fJames Hogan# ifndef PTRACE_SET_SYSCALL
143905eb905c4433c60d538e134619a3117522072a2fJames Hogan#  define PTRACE_SET_SYSCALL 23
144005eb905c4433c60d538e134619a3117522072a2fJames Hogan# endif
144105eb905c4433c60d538e134619a3117522072a2fJames Hogan	if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
144205eb905c4433c60d538e134619a3117522072a2fJames Hogan		return -1;
144305eb905c4433c60d538e134619a3117522072a2fJames Hogan	return 0;
1444bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko#elif defined(AARCH64)
1445bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* setbpt/clearbpt never used: */
1446bf357fcb76baeb64a45fc2b6b355c913c63e6015Denys Vlasenko	/* AARCH64 is only supported since about linux-3.0.31 */
144705eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(TILE)
1448d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* setbpt/clearbpt never used: */
1449d27809c978f3c8c3271f7d726dc92dd0eefa8a0fDenys Vlasenko	/* Tilera CPUs are only supported since about linux-2.6.34 */
145005eb905c4433c60d538e134619a3117522072a2fJames Hogan#elif defined(MICROBLAZE)
1451a86696ba6417eeebc92d8ee232d626d97bc8a048Denys Vlasenko	/* setbpt/clearbpt never used: */
1452a86696ba6417eeebc92d8ee232d626d97bc8a048Denys Vlasenko	/* microblaze is only supported since about linux-2.6.30 */
1453492f81f14cc86c13b0f67ac66a3d5ea9f6ccb673Christian Svensson#elif defined(OR1K)
1454492f81f14cc86c13b0f67ac66a3d5ea9f6ccb673Christian Svensson	/* never reached; OR1K is only supported by kernels since 3.1.0. */
14555f999a869b681ff69cbb801225677fc125b6aefdJames Hogan#elif defined(METAG)
14565f999a869b681ff69cbb801225677fc125b6aefdJames Hogan	/* setbpt/clearbpt never used: */
14575f999a869b681ff69cbb801225677fc125b6aefdJames Hogan	/* Meta is only supported since linux-3.7 */
14588f636ed12870cdc8e4b38194eb4b701f42ad222bChris Zankel#elif defined(XTENSA)
14598f636ed12870cdc8e4b38194eb4b701f42ad222bChris Zankel	/* setbpt/clearbpt never used: */
14608f636ed12870cdc8e4b38194eb4b701f42ad222bChris Zankel	/* Xtensa is only supported since linux 2.6.13 */
14617daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#elif defined(ARC)
14627daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta	/* setbpt/clearbpt never used: */
14637daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta	/* ARC only supported since 3.9 */
146405eb905c4433c60d538e134619a3117522072a2fJames Hogan#else
146505eb905c4433c60d538e134619a3117522072a2fJames Hogan#warning Do not know how to handle change_syscall for this architecture
146605eb905c4433c60d538e134619a3117522072a2fJames Hogan#endif /* architecture */
146705eb905c4433c60d538e134619a3117522072a2fJames Hogan	return -1;
146805eb905c4433c60d538e134619a3117522072a2fJames Hogan}
146905eb905c4433c60d538e134619a3117522072a2fJames Hogan
1470d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
1471418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkosetbpt(struct tcb *tcp)
1472d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
14733291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1474d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1475d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1476d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	if (tcp->flags & TCB_BPTSET) {
1477d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1478d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return -1;
1479d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1480d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
14813291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	/*
14823291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * It's a silly kludge to initialize this with a search at runtime.
14833291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * But it's better than maintaining another magic thing in the
14843291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 * godforsaken tables.
14853291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	 */
14863291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	if (clone_scno[current_personality] == 0) {
14873291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		int i;
14883291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath		for (i = 0; i < nsyscalls; ++i)
14893291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			if (sysent[i].sys_func == sys_clone) {
14903291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				clone_scno[current_personality] = i;
14913291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath				break;
14923291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath			}
14933291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath	}
14943291ef2013cf9510f8ca493ab1c81862fd3a5e15Roland McGrath
14956556315493082df9a24dbce9dadea4d6673e9965Dmitry V. Levin	if (tcp->s_ent->sys_func == sys_fork) {
1496b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (arg_setup(tcp, &state) < 0
1497b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1498b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || get_arg1(tcp, &state, &tcp->inst[1]) < 0
149905eb905c4433c60d538e134619a3117522072a2fJames Hogan		    || change_syscall(tcp, &state,
150005eb905c4433c60d538e134619a3117522072a2fJames Hogan				      clone_scno[current_personality]) < 0
1501b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1502b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || set_arg1(tcp, &state, 0) < 0
1503b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		    || arg_finish_change(tcp, &state) < 0)
1504d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath			return -1;
1505c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1506c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->u_arg[arg1_index] = 0;
1507d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		tcp->flags |= TCB_BPTSET;
1508d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
15090c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	}
1510d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
151174ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko	if (tcp->s_ent->sys_func == sys_clone) {
15128fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		/* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
15130c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin		   contrary to x86 vfork above.  Even on x86 we turn the
15148fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   vfork semantics into plain fork - each application must not
15158fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   depend on the vfork specifics according to POSIX.  We would
15168fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   hang waiting for the parent resume otherwise.  We need to
15178fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   clear also CLONE_VM but only in the CLONE_VFORK case as
15188fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil		   otherwise we would break pthread_create.  */
15198fc9575e0b45aae0af00e73da2d7b7bca5ebbf13Jan Kratochvil
1520c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1521c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (new_arg0 & CLONE_VFORK)
1522c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1523c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (arg_setup(tcp, &state) < 0
1524c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || set_arg0(tcp, &state, new_arg0) < 0
1525c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		 || arg_finish_change(tcp, &state) < 0)
15265ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			return -1;
1527c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[0] = tcp->u_arg[arg0_index];
1528c9dc3c1ea77e24e531bde164ba90cc226b1305f8Roland McGrath		tcp->inst[1] = tcp->u_arg[arg1_index];
152955980f5b72000406e3fd843b098b5c1328a21e45Denys Vlasenko		tcp->flags |= TCB_BPTSET;
1530d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath		return 0;
1531d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	}
1532d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
15330c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin	fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
15340c661513e5a4594cfae98042018ed549b1e26b8dDmitry V. Levin		tcp->scno, tcp->pid);
1535d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return -1;
1536d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1537d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath
1538d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrathint
15391201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoclearbpt(struct tcb *tcp)
1540d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath{
1541d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	arg_setup_state state;
1542b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (arg_setup(tcp, &state) < 0
154305eb905c4433c60d538e134619a3117522072a2fJames Hogan	    || change_syscall(tcp, &state, tcp->scno) < 0
1544b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1545b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1546b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	    || arg_finish_change(tcp, &state))
1547c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko		if (errno != ESRCH)
1548c133bf0eb240de31856f82972cf7f6f1e512780bDenys Vlasenko			return -1;
1549d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	tcp->flags &= ~TCB_BPTSET;
1550d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath	return 0;
1551d81f1d9aac84cbed9d9dcde84fa44f8b1f9b6a66Roland McGrath}
1552