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