blob: cd4b802230a7b650ef965c0f0551923592da3bae [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
36#include <sys/param.h>
37#include <fcntl.h>
Masatake YAMATOf5480672014-11-22 19:03:33 +090038#if HAVE_SYS_XATTR_H
39# include <sys/xattr.h>
40#endif
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000041#include <sys/uio.h>
Wichert Akkerman36915a11999-07-13 15:45:02 +000042
Denys Vlasenko84703742012-02-25 02:38:52 +010043#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000044# include <asm/ptrace_offsets.h>
45# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000046#endif
47
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010049# include <sys/reg.h>
Maarten ter Huurne40c174b2014-10-20 01:02:48 +020050#endif
51
52#ifdef HAVE_LINUX_PTRACE_H
Denys Vlasenko84703742012-02-25 02:38:52 +010053# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000054# ifdef HAVE_STRUCT_IA64_FPREG
55# define ia64_fpreg XXX_ia64_fpreg
56# endif
57# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
58# define pt_all_user_regs XXX_pt_all_user_regs
59# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030060# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
61# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
62# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010063# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030064# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000065# undef ia64_fpreg
66# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000070string_to_uint(const char *str)
71{
72 char *error;
73 long value;
74
75 if (!*str)
76 return -1;
77 errno = 0;
78 value = strtol(str, &error, 10);
79 if (errno || *error || value < 0 || (long)(int)value != value)
80 return -1;
81 return (int)value;
82}
83
84int
Dmitry V. Levin447db452014-05-29 17:59:01 +000085tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086{
87 return a->tv_sec || a->tv_usec;
88}
89
90int
Dmitry V. Levin447db452014-05-29 17:59:01 +000091tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092{
93 if (a->tv_sec < b->tv_sec
94 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
95 return -1;
96 if (a->tv_sec > b->tv_sec
97 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
98 return 1;
99 return 0;
100}
101
102double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000103tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104{
105 return tv->tv_sec + tv->tv_usec/1000000.0;
106}
107
108void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000109tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110{
111 tv->tv_sec = a->tv_sec + b->tv_sec;
112 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000113 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114 tv->tv_sec++;
115 tv->tv_usec -= 1000000;
116 }
117}
118
119void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000120tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121{
122 tv->tv_sec = a->tv_sec - b->tv_sec;
123 tv->tv_usec = a->tv_usec - b->tv_usec;
124 if (((long) tv->tv_usec) < 0) {
125 tv->tv_sec--;
126 tv->tv_usec += 1000000;
127 }
128}
129
130void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000131tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132{
133 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
134 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
135 tv->tv_usec %= 1000000;
136}
137
138void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000139tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140{
141 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000142 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143 tv->tv_usec %= 1000000;
144}
145
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000146const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000147xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148{
149 for (; xlat->str != NULL; xlat++)
150 if (xlat->val == val)
151 return xlat->str;
152 return NULL;
153}
154
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000155static int
156xlat_bsearch_compare(const void *a, const void *b)
157{
158 const unsigned int val1 = (const unsigned long) a;
159 const unsigned int val2 = ((const struct xlat *) b)->val;
160 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
161}
162
163const char *
164xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
165{
166 const struct xlat *e =
167 bsearch((const void*) (const unsigned long) val,
168 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
169
170 return e ? e->str : NULL;
171}
172
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200173#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200174char *
175stpcpy(char *dst, const char *src)
176{
177 while ((*dst = *src++) != '\0')
178 dst++;
179 return dst;
180}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200181#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200182
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100183/* Find a next bit which is set.
184 * Starts testing at cur_bit.
185 * Returns -1 if no more bits are set.
186 *
187 * We never touch bytes we don't need to.
188 * On big-endian, array is assumed to consist of
189 * current_wordsize wide words: for example, is current_wordsize is 4,
190 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
191 * On little-endian machines, word size is immaterial.
192 */
193int
194next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
195{
196 const unsigned endian = 1;
197 int little_endian = *(char*)&endian;
198
199 const uint8_t *array = bit_array;
200 unsigned pos = cur_bit / 8;
201 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
202
203 for (;;) {
204 uint8_t bitmask;
205 uint8_t cur_byte;
206
207 if (cur_bit >= size_bits)
208 return -1;
209 cur_byte = array[pos ^ pos_xor_mask];
210 if (cur_byte == 0) {
211 cur_bit = (cur_bit + 8) & (-8);
212 pos++;
213 continue;
214 }
215 bitmask = 1 << (cur_bit & 7);
216 for (;;) {
217 if (cur_byte & bitmask)
218 return cur_bit;
219 cur_bit++;
220 if (cur_bit >= size_bits)
221 return -1;
222 bitmask <<= 1;
223 /* This check *can't be* optimized out: */
224 if (bitmask == 0)
225 break;
226 }
227 pos++;
228 }
229}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230/*
231 * Print entry in struct xlat table, if there.
232 */
233void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000234printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000236 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237
238 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200239 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 else
241 tprintf("%#x /* %s */", val, dflt);
242}
243
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100244/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100245 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100246 * argument.
247 */
248int
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000249printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100250{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000251#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
252# if SUPPORTED_PERSONALITIES > 1
253 if (current_wordsize > 4) {
254# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100255 tprintf(format, tcp->u_arg[arg_no]);
256 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000257# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100258 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000259# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000260 /* Align arg_no to the next even number. */
261 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000262# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100263 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
264 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100265 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000266# endif /* SUPPORTED_PERSONALITIES */
267#elif SIZEOF_LONG > 4
268# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
269#elif defined LINUX_MIPSN32
270 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100271 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000272#elif defined X32
273 if (current_personality == 0) {
274 tprintf(format, tcp->ext_arg[arg_no]);
275 arg_no++;
276 } else {
277 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
278 arg_no += 2;
279 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100280#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000281# if defined __ARM_EABI__ || \
282 defined LINUX_MIPSO32 || \
283 defined POWERPC || \
284 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000285 /* Align arg_no to the next even number. */
286 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000287# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100288 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
289 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100290#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000291
Chris Metcalf879dddd2013-03-01 10:41:02 +0100292 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100293}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100294
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295/*
296 * Interpret `xlat' as an array of flags
297 * print the entries whose bits are on in `flags'
298 * return # of flags printed.
299 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200300void
Denys Vlasenko12014262011-05-30 14:00:14 +0200301addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200303 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304 if (xlat->val && (flags & xlat->val) == xlat->val) {
305 tprintf("|%s", xlat->str);
306 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307 }
308 }
309 if (flags) {
310 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312}
313
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000314/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200315 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000316 * Print to static string the entries whose bits are on in `flags'
317 * Return static string.
318 */
319const char *
320sprintflags(const char *prefix, const struct xlat *xlat, int flags)
321{
322 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200323 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000324 int found = 0;
325
Denys Vlasenko52845572011-08-31 12:07:38 +0200326 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000327
328 for (; xlat->str; xlat++) {
329 if ((flags & xlat->val) == xlat->val) {
330 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200331 *outptr++ = '|';
332 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000333 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100334 flags &= ~xlat->val;
335 if (!flags)
336 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000337 }
338 }
339 if (flags) {
340 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200341 *outptr++ = '|';
342 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000343 }
344
345 return outstr;
346}
347
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000348int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000349printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350{
351 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000352 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353
354 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200355 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356 return 1;
357 }
358
359 sep = "";
360 for (n = 0; xlat->str; xlat++) {
361 if (xlat->val && (flags & xlat->val) == xlat->val) {
362 tprintf("%s%s", sep, xlat->str);
363 flags &= ~xlat->val;
364 sep = "|";
365 n++;
366 }
367 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000368
369 if (n) {
370 if (flags) {
371 tprintf("%s%#x", sep, flags);
372 n++;
373 }
374 } else {
375 if (flags) {
376 tprintf("%#x", flags);
377 if (dflt)
378 tprintf(" /* %s */", dflt);
379 } else {
380 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200381 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000382 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000384
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 return n;
386}
387
388void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000389printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390{
Roland McGratheb285352003-01-14 09:59:00 +0000391 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392
393 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200394 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000395 return;
396 }
397 if (umove(tcp, addr, &num) < 0) {
398 tprintf("%#lx", addr);
399 return;
400 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200401 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200403 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404}
405
Roland McGrath6bc12202003-11-13 22:32:27 +0000406void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000407printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000408{
409 int num;
410
411 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200412 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000413 return;
414 }
415 if (umove(tcp, addr, &num) < 0) {
416 tprintf("%#lx", addr);
417 return;
418 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200419 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000420 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200421 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000422}
423
Masatake YAMATOf5480672014-11-22 19:03:33 +0900424static char *
425getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
426{
427#if HAVE_SYS_XATTR_H
428 ssize_t r;
429 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
430
431 if (fd < 0)
432 return NULL;
433
434 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
435 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
436 if (r <= 0)
437 return NULL;
438 else {
439 /*
440 * This is a protection for the case when the kernel
441 * side does not append a null byte to the buffer.
442 */
443 buf[r] = '\0';
444 return buf;
445 }
446#else
447 return NULL;
448#endif
449}
450
Roland McGrath9814a942005-07-04 23:28:10 +0000451void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300452printfd(struct tcb *tcp, int fd)
453{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100454 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000455 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
456 static const char socket_prefix[] = "socket:[";
457 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
458 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000459
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000460 if (show_fd_path > 1 &&
461 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
462 path[(path_len = strlen(path)) - 1] == ']') {
463 unsigned long inodenr;
464 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
465 tprintf("%d<", fd);
Masatake YAMATOf5480672014-11-22 19:03:33 +0900466 if (!print_sockaddr_by_inode(inodenr)) {
467#define PROTO_NAME_LEN 32
468 char proto_buf[PROTO_NAME_LEN];
469 const char *proto =
470 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
471
472 if (proto)
473 tprintf("%s:[%lu]", proto, inodenr);
474 else
475 tprints(path);
476 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000477 tprints(">");
478 } else {
479 tprintf("%d<%s>", fd, path);
480 }
481 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000482 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300483}
484
485void
Denys Vlasenko12014262011-05-30 14:00:14 +0200486printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000487{
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000488 tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000489}
490
Dmitry V. Levina501f142008-11-10 23:19:13 +0000491/*
492 * Quote string `instr' of length `size'
493 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200494 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000495 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100496 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200497 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100498 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000499 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400500int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200501string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000502{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000503 const unsigned char *ustr = (const unsigned char *) instr;
504 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200505 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200507 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200508 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200509 size--;
510 eol = '\0';
511 }
512
513 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000514 if (xflag > 1)
515 usehex = 1;
516 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000517 /* Check for presence of symbol which require
518 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000519 for (i = 0; i < size; ++i) {
520 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000521 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200522 if (c == eol)
523 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100524
525 /* Force hex unless c is printable or whitespace */
526 if (c > 0x7e) {
527 usehex = 1;
528 break;
529 }
530 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
531 * They happen to have ASCII codes 9,10,11,12,13.
532 */
533 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000534 usehex = 1;
535 break;
536 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 }
538 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000539
540 *s++ = '\"';
541
542 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000543 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000544 for (i = 0; i < size; ++i) {
545 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000546 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200547 if (c == eol)
548 goto asciz_ended;
549 *s++ = '\\';
550 *s++ = 'x';
551 *s++ = "0123456789abcdef"[c >> 4];
552 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553 }
554 } else {
555 for (i = 0; i < size; ++i) {
556 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000557 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200558 if (c == eol)
559 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000560 switch (c) {
561 case '\"': case '\\':
562 *s++ = '\\';
563 *s++ = c;
564 break;
565 case '\f':
566 *s++ = '\\';
567 *s++ = 'f';
568 break;
569 case '\n':
570 *s++ = '\\';
571 *s++ = 'n';
572 break;
573 case '\r':
574 *s++ = '\\';
575 *s++ = 'r';
576 break;
577 case '\t':
578 *s++ = '\\';
579 *s++ = 't';
580 break;
581 case '\v':
582 *s++ = '\\';
583 *s++ = 'v';
584 break;
585 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100586 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000587 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200588 else {
589 /* Print \octal */
590 *s++ = '\\';
591 if (i + 1 < size
592 && ustr[i + 1] >= '0'
593 && ustr[i + 1] <= '9'
594 ) {
595 /* Print \ooo */
596 *s++ = '0' + (c >> 6);
597 *s++ = '0' + ((c >> 3) & 0x7);
598 } else {
599 /* Print \[[o]o]o */
600 if ((c >> 3) != 0) {
601 if ((c >> 6) != 0)
602 *s++ = '0' + (c >> 6);
603 *s++ = '0' + ((c >> 3) & 0x7);
604 }
605 }
606 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000607 }
608 break;
609 }
610 }
611 }
612
613 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000615
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200616 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200617 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200618 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
619 * but next char is NUL.
620 */
621 return 0;
622 }
623
624 return 1;
625
626 asciz_ended:
627 *s++ = '\"';
628 *s = '\0';
629 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
630 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631}
632
Dmitry V. Levina501f142008-11-10 23:19:13 +0000633/*
634 * Print path string specified by address `addr' and length `n'.
635 * If path length exceeds `n', append `...' to the output.
636 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000637void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000638printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000640 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100641 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100642
Dmitry V. Levina501f142008-11-10 23:19:13 +0000643 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200644 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000645 return;
646 }
647
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100648 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000649 if (n > sizeof path - 1)
650 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000651
652 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100653 nul_seen = umovestr(tcp, addr, n + 1, path);
654 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 tprintf("%#lx", addr);
656 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100657 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000658
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100659 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100660 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100661 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100662 string_quote(path, outstr, -1, n);
663 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100664 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100665 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 }
667}
668
669void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000670printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100672 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000673 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000674}
675
Dmitry V. Levina501f142008-11-10 23:19:13 +0000676/*
677 * Print string specified by address `addr' and length `len'.
678 * If `len' < 0, treat the string as a NUL-terminated string.
679 * If string length exceeds `max_strlen', append `...' to the output.
680 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000681void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200682printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000683{
684 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000686 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100687 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688
689 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200690 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691 return;
692 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000693 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200694 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000695 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
696
697 if (outstr_size / 4 != max_strlen)
698 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000699 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200700 if (!str)
701 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000702 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200703 if (!outstr)
704 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000706
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200707 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000708 /*
709 * Treat as a NUL-terminated string: fetch one byte more
710 * because string_quote() quotes one byte less.
711 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000712 size = max_strlen + 1;
713 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 tprintf("%#lx", addr);
715 return;
716 }
717 }
718 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200719 size = max_strlen;
720 if (size > (unsigned long)len)
721 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000722 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 tprintf("%#lx", addr);
724 return;
725 }
726 }
727
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100728 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
729 * or we were requested to print more than -s NUM chars)...
730 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100731 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000732 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000733
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100734 tprints(outstr);
735 if (ellipsis)
736 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737}
738
John Hughes1d08dcf2001-07-10 13:48:44 +0000739void
Denys Vlasenko12014262011-05-30 14:00:14 +0200740dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000741{
Denys Vlasenko84703742012-02-25 02:38:52 +0100742#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000743 union {
744 struct { u_int32_t base; u_int32_t len; } *iov32;
745 struct { u_int64_t base; u_int64_t len; } *iov64;
746 } iovu;
747#define iov iovu.iov64
748#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100749 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000750#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100751 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000752#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100753 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000754#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000755 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000756#define sizeof_iov sizeof(*iov)
757#define iov_iov_base(i) iov[i].iov_base
758#define iov_iov_len(i) iov[i].iov_len
759#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000760 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200761 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000762
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200763 size = sizeof_iov * len;
764 /* Assuming no sane program has millions of iovs */
765 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000766 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200767 fprintf(stderr, "Out of memory\n");
768 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000769 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000770 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000771 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000772 /* include the buffer number to make it easy to
773 * match up the trace with the source */
774 tprintf(" * %lu bytes in buffer %d\n",
775 (unsigned long)iov_iov_len(i), i);
776 dumpstr(tcp, (long) iov_iov_base(i),
777 iov_iov_len(i));
778 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000779 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200780 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000781#undef sizeof_iov
782#undef iov_iov_base
783#undef iov_iov_len
784#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000785}
John Hughes1d08dcf2001-07-10 13:48:44 +0000786
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787void
Denys Vlasenko12014262011-05-30 14:00:14 +0200788dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789{
790 static int strsize = -1;
791 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792
Denys Vlasenko76325802013-02-22 14:47:39 +0100793 char outbuf[
794 (
795 (sizeof(
796 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
797 "1234567890123456") + /*in case I'm off by few:*/ 4)
798 /*align to 8 to make memset easier:*/ + 7) & -8
799 ];
800 const unsigned char *src;
801 int i;
802
803 memset(outbuf, ' ', sizeof(outbuf));
804
805 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200806 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100807 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200808 if (!str) {
809 strsize = -1;
810 fprintf(stderr, "Out of memory\n");
811 return;
812 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100813 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 }
815
816 if (umoven(tcp, addr, len, (char *) str) < 0)
817 return;
818
Denys Vlasenko76325802013-02-22 14:47:39 +0100819 /* Space-pad to 16 bytes */
820 i = len;
821 while (i & 0xf)
822 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200823
Denys Vlasenko76325802013-02-22 14:47:39 +0100824 i = 0;
825 src = str;
826 while (i < len) {
827 char *dst = outbuf;
828 /* Hex dump */
829 do {
830 if (i < len) {
831 *dst++ = "0123456789abcdef"[*src >> 4];
832 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000833 }
834 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100835 *dst++ = ' ';
836 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100838 dst++; /* space is there by memset */
839 i++;
840 if ((i & 7) == 0)
841 dst++; /* space is there by memset */
842 src++;
843 } while (i & 0xf);
844 /* ASCII dump */
845 i -= 16;
846 src -= 16;
847 do {
848 if (*src >= ' ' && *src < 0x7f)
849 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100851 *dst++ = '.';
852 src++;
853 } while (++i & 0xf);
854 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100855 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000856 }
857}
858
Mike Frysinger612659e2012-02-14 14:38:28 +0100859#ifdef HAVE_PROCESS_VM_READV
860/* C library supports this, but the kernel might not. */
861static bool process_vm_readv_not_supported = 0;
862#else
863
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100864/* Need to do this since process_vm_readv() is not yet available in libc.
865 * When libc is be updated, only "static bool process_vm_readv_not_supported"
866 * line should remain.
867 */
868#if !defined(__NR_process_vm_readv)
869# if defined(I386)
870# define __NR_process_vm_readv 347
871# elif defined(X86_64)
872# define __NR_process_vm_readv 310
873# elif defined(POWERPC)
874# define __NR_process_vm_readv 351
875# endif
876#endif
877
878#if defined(__NR_process_vm_readv)
879static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400880/* Have to avoid duplicating with the C library headers. */
881static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100882 const struct iovec *lvec,
883 unsigned long liovcnt,
884 const struct iovec *rvec,
885 unsigned long riovcnt,
886 unsigned long flags)
887{
888 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
889}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400890#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100891#else
892static bool process_vm_readv_not_supported = 1;
893# define process_vm_readv(...) (errno = ENOSYS, -1)
894#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100895
896#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100897
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898#define PAGMASK (~(PAGSIZ - 1))
899/*
900 * move `len' bytes of data from process `pid'
901 * at address `addr' to our space at `laddr'
902 */
903int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000904umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700906 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000907 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 union {
909 long val;
910 char x[sizeof(long)];
911 } u;
912
Denys Vlasenko2544f982013-02-19 17:39:56 +0100913#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100914 if (current_wordsize < sizeof(addr))
915 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100916#endif
917
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100918 if (!process_vm_readv_not_supported) {
919 struct iovec local[1], remote[1];
920 int r;
921
922 local[0].iov_base = laddr;
923 remote[0].iov_base = (void*)addr;
924 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000925 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100926 if (r == len)
927 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000928 if (r >= 0) {
929 error_msg("umoven: short read (%d < %d) @0x%lx",
930 r, len, addr);
931 return -1;
932 }
933 switch (errno) {
934 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100935 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000936 break;
937 case ESRCH:
938 /* the process is gone */
939 return -1;
940 case EFAULT: case EIO: case EPERM:
941 /* address space is inaccessible */
942 return -1;
943 default:
944 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100945 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000946 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100947 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100948 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100949
Dmitry V. Levin97005922013-02-26 21:16:22 +0000950 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 if (addr & (sizeof(long) - 1)) {
952 /* addr not a multiple of sizeof(long) */
953 n = addr - (addr & -sizeof(long)); /* residue */
954 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700955 errno = 0;
956 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000957 switch (errno) {
958 case 0:
959 break;
960 case ESRCH: case EINVAL:
961 /* these could be seen if the process is gone */
962 return -1;
963 case EFAULT: case EIO: case EPERM:
964 /* address space is inaccessible */
965 return -1;
966 default:
967 /* all the rest is strange and should be reported */
968 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
969 pid, addr);
970 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700971 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100972 m = MIN(sizeof(long) - n, len);
973 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100974 addr += sizeof(long);
975 laddr += m;
976 nread += m;
977 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 }
979 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700980 errno = 0;
981 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000982 switch (errno) {
983 case 0:
984 break;
985 case ESRCH: case EINVAL:
986 /* these could be seen if the process is gone */
987 return -1;
988 case EFAULT: case EIO: case EPERM:
989 /* address space is inaccessible */
990 if (nread) {
991 perror_msg("umoven: short read (%d < %d) @0x%lx",
992 nread, nread + len, addr - nread);
993 }
994 return -1;
995 default:
996 /* all the rest is strange and should be reported */
997 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
998 pid, addr);
999 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001000 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001001 m = MIN(sizeof(long), len);
1002 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001003 addr += sizeof(long);
1004 laddr += m;
1005 nread += m;
1006 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 return 0;
1010}
1011
1012/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001013 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001015 *
1016 * Returns < 0 on error, > 0 if NUL was seen,
1017 * (TODO if useful: return count of bytes including NUL),
1018 * else 0 if len bytes were read but no NUL byte seen.
1019 *
1020 * Note: there is no guarantee we won't overwrite some bytes
1021 * in laddr[] _after_ terminating NUL (but, of course,
1022 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 */
1024int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001025umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026{
Denys Vlasenko16940922013-03-01 18:52:59 +01001027#if SIZEOF_LONG == 4
1028 const unsigned long x01010101 = 0x01010101ul;
1029 const unsigned long x80808080 = 0x80808080ul;
1030#elif SIZEOF_LONG == 8
1031 const unsigned long x01010101 = 0x0101010101010101ul;
1032 const unsigned long x80808080 = 0x8080808080808080ul;
1033#else
1034# error SIZEOF_LONG > 8
1035#endif
1036
Roland McGratheb9e2e82009-06-02 16:49:22 -07001037 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +01001038 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001040 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 char x[sizeof(long)];
1042 } u;
1043
Denys Vlasenko2544f982013-02-19 17:39:56 +01001044#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001045 if (current_wordsize < sizeof(addr))
1046 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001047#endif
1048
Dmitry V. Levin97005922013-02-26 21:16:22 +00001049 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001050 if (!process_vm_readv_not_supported) {
1051 struct iovec local[1], remote[1];
1052
1053 local[0].iov_base = laddr;
1054 remote[0].iov_base = (void*)addr;
1055
1056 while (len > 0) {
1057 int end_in_page;
1058 int r;
1059 int chunk_len;
1060
1061 /* Don't read kilobytes: most strings are short */
1062 chunk_len = len;
1063 if (chunk_len > 256)
1064 chunk_len = 256;
1065 /* Don't cross pages. I guess otherwise we can get EFAULT
1066 * and fail to notice that terminating NUL lies
1067 * in the existing (first) page.
1068 * (I hope there aren't arches with pages < 4K)
1069 */
1070 end_in_page = ((addr + chunk_len) & 4095);
1071 r = chunk_len - end_in_page;
1072 if (r > 0) /* if chunk_len > end_in_page */
1073 chunk_len = r; /* chunk_len -= end_in_page */
1074
1075 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001076 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1077 if (r > 0) {
1078 if (memchr(local[0].iov_base, '\0', r))
1079 return 1;
1080 local[0].iov_base += r;
1081 remote[0].iov_base += r;
1082 len -= r;
1083 nread += r;
1084 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001085 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001086 switch (errno) {
1087 case ENOSYS:
1088 process_vm_readv_not_supported = 1;
1089 goto vm_readv_didnt_work;
1090 case ESRCH:
1091 /* the process is gone */
1092 return -1;
1093 case EFAULT: case EIO: case EPERM:
1094 /* address space is inaccessible */
1095 if (nread) {
1096 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1097 nread, nread + len, addr);
1098 }
1099 return -1;
1100 default:
1101 /* all the rest is strange and should be reported */
1102 perror_msg("process_vm_readv");
1103 return -1;
1104 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001105 }
1106 return 0;
1107 }
1108 vm_readv_didnt_work:
1109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 if (addr & (sizeof(long) - 1)) {
1111 /* addr not a multiple of sizeof(long) */
1112 n = addr - (addr & -sizeof(long)); /* residue */
1113 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001114 errno = 0;
1115 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001116 switch (errno) {
1117 case 0:
1118 break;
1119 case ESRCH: case EINVAL:
1120 /* these could be seen if the process is gone */
1121 return -1;
1122 case EFAULT: case EIO: case EPERM:
1123 /* address space is inaccessible */
1124 return -1;
1125 default:
1126 /* all the rest is strange and should be reported */
1127 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1128 pid, addr);
1129 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001130 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001131 m = MIN(sizeof(long) - n, len);
1132 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 while (n & (sizeof(long) - 1))
1134 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001135 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001136 addr += sizeof(long);
1137 laddr += m;
1138 nread += m;
1139 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001141
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001143 errno = 0;
1144 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001145 switch (errno) {
1146 case 0:
1147 break;
1148 case ESRCH: case EINVAL:
1149 /* these could be seen if the process is gone */
1150 return -1;
1151 case EFAULT: case EIO: case EPERM:
1152 /* address space is inaccessible */
1153 if (nread) {
1154 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1155 nread, nread + len, addr - nread);
1156 }
1157 return -1;
1158 default:
1159 /* all the rest is strange and should be reported */
1160 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1161 pid, addr);
1162 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001163 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001164 m = MIN(sizeof(long), len);
1165 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001166 /* "If a NUL char exists in this word" */
1167 if ((u.val - x01010101) & ~u.val & x80808080)
1168 return 1;
1169 addr += sizeof(long);
1170 laddr += m;
1171 nread += m;
1172 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001174 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175}
1176
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001178upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179{
1180 long val;
1181
Roland McGratheb9e2e82009-06-02 16:49:22 -07001182 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001183 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001184 if (val == -1 && errno) {
1185 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001186 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001187 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001189 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 *res = val;
1191 return 0;
1192}
1193
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001194/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1195 * and PTRACE_O_TRACE[V]FORK for tracing children.
1196 * If you are adding a new arch which is only supported by newer kernels,
1197 * you most likely don't need to add any code below
1198 * beside a dummy "return 0" block in change_syscall().
1199 */
1200
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001201/*
1202 * These #if's are huge, please indent them correctly.
1203 * It's easy to get confused otherwise.
1204 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001206#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001207
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001208#ifndef CLONE_PTRACE
1209# define CLONE_PTRACE 0x00002000
1210#endif
1211#ifndef CLONE_VFORK
1212# define CLONE_VFORK 0x00004000
1213#endif
1214#ifndef CLONE_VM
1215# define CLONE_VM 0x00000100
1216#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001217
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001218#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001219
1220typedef unsigned long *arg_setup_state;
1221
1222static int
1223arg_setup(struct tcb *tcp, arg_setup_state *state)
1224{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001225 unsigned long cfm, sof, sol;
1226 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001227
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001228 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001229 /* Satisfy a false GCC warning. */
1230 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001231 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001232 }
Roland McGrath08267b82004-02-20 22:56:43 +00001233
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001234 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001235 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001236 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001237 return -1;
1238
1239 sof = (cfm >> 0) & 0x7f;
1240 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001241 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001242
Jan Kratochvil1f942712008-08-06 21:38:52 +00001243 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001244 return 0;
1245}
1246
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001247# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248
Roland McGrathd81f1d92003-01-09 06:53:34 +00001249static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001250get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001251{
Roland McGrath08267b82004-02-20 22:56:43 +00001252 int ret;
1253
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001254 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001255 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001256 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001257 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001258 (unsigned long) ia64_rse_skip_regs(*state, 0),
1259 sizeof(long), (void *) valp);
1260 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261}
1262
1263static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001264get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265{
Roland McGrath08267b82004-02-20 22:56:43 +00001266 int ret;
1267
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001268 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001269 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001270 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001271 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001272 (unsigned long) ia64_rse_skip_regs(*state, 1),
1273 sizeof(long), (void *) valp);
1274 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001276
1277static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001278set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279{
Roland McGrath08267b82004-02-20 22:56:43 +00001280 int req = PTRACE_POKEDATA;
1281 void *ap;
1282
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001283 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001284 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1285 req = PTRACE_POKEUSER;
1286 } else
1287 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001288 errno = 0;
1289 ptrace(req, tcp->pid, ap, val);
1290 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291}
1292
1293static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001294set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295{
Roland McGrath08267b82004-02-20 22:56:43 +00001296 int req = PTRACE_POKEDATA;
1297 void *ap;
1298
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001299 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001300 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1301 req = PTRACE_POKEUSER;
1302 } else
1303 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001304 errno = 0;
1305 ptrace(req, tcp->pid, ap, val);
1306 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307}
1308
Roland McGrathb659f872008-07-18 01:19:36 +00001309/* ia64 does not return the input arguments from functions (and syscalls)
1310 according to ia64 RSE (Register Stack Engine) behavior. */
1311
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001312# define restore_arg0(tcp, state, val) ((void) (state), 0)
1313# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001314
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001315#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001316
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001317# if defined(SPARC64)
1318# undef PTRACE_GETREGS
1319# define PTRACE_GETREGS PTRACE_GETREGS64
1320# undef PTRACE_SETREGS
1321# define PTRACE_SETREGS PTRACE_SETREGS64
1322# endif
1323
Mike Frysinger8566c502009-10-12 11:05:14 -04001324typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001325
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001326# define arg_setup(tcp, state) \
1327 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1328# define arg_finish_change(tcp, state) \
1329 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001331# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1332# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1333# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1334# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1335# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001337#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001339# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001340/* Note: this is only true for the `clone' system call, which handles
1341 arguments specially. We could as well say that its first two arguments
1342 are swapped relative to other architectures, but that would just be
1343 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001344# define arg0_offset PT_GPR3
1345# define arg1_offset PT_ORIGGPR2
1346# define restore_arg0(tcp, state, val) ((void) (state), 0)
1347# define restore_arg1(tcp, state, val) ((void) (state), 0)
1348# define arg0_index 1
1349# define arg1_index 0
1350# elif defined(ALPHA) || defined(MIPS)
1351# define arg0_offset REG_A0
1352# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001353# elif defined(POWERPC)
1354# define arg0_offset (sizeof(unsigned long)*PT_R3)
1355# define arg1_offset (sizeof(unsigned long)*PT_R4)
1356# define restore_arg0(tcp, state, val) ((void) (state), 0)
1357# elif defined(HPPA)
1358# define arg0_offset PT_GR26
1359# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001360# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001361# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1362# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1363# elif defined(SH)
1364# define arg0_offset (4*(REG_REG0+4))
1365# define arg1_offset (4*(REG_REG0+5))
1366# elif defined(SH64)
1367 /* ABI defines arg0 & 1 in r2 & r3 */
1368# define arg0_offset (REG_OFFSET+16)
1369# define arg1_offset (REG_OFFSET+24)
1370# define restore_arg0(tcp, state, val) 0
1371# elif defined CRISV10 || defined CRISV32
1372# define arg0_offset (4*PT_R11)
1373# define arg1_offset (4*PT_ORIG_R10)
1374# define restore_arg0(tcp, state, val) 0
1375# define restore_arg1(tcp, state, val) 0
1376# define arg0_index 1
1377# define arg1_index 0
1378# else
1379# define arg0_offset 0
1380# define arg1_offset 4
1381# if defined ARM
1382# define restore_arg0(tcp, state, val) 0
1383# endif
1384# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001385
1386typedef int arg_setup_state;
1387
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001388# define arg_setup(tcp, state) (0)
1389# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001390# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1391# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001392
1393static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001394set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001395{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001396 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001397}
1398
1399static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001400set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001402 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001403}
1404
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001405#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001407#ifndef restore_arg0
1408# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1409#endif
1410#ifndef restore_arg1
1411# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1412#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001414#ifndef arg0_index
1415# define arg0_index 0
1416# define arg1_index 1
1417#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001418
James Hogan05eb9052012-11-29 17:37:37 +00001419static int
1420change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1421{
1422#if defined(I386)
1423 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1424 return -1;
1425 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001426#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001427 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1428 return -1;
1429 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001430#elif defined(X32)
1431 /* setbpt/clearbpt never used: */
1432 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001433#elif defined(POWERPC)
1434 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1435 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1436 return -1;
1437 return 0;
1438#elif defined(S390) || defined(S390X)
1439 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1440 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1441 return -1;
1442 return 0;
1443#elif defined(M68K)
1444 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1445 return -1;
1446 return 0;
1447#elif defined(SPARC) || defined(SPARC64)
1448 state->u_regs[U_REG_G1] = new;
1449 return 0;
1450#elif defined(MIPS)
1451 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1452 return -1;
1453 return 0;
1454#elif defined(ALPHA)
1455 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1456 return -1;
1457 return 0;
1458#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001459 /* setbpt/clearbpt never used: */
1460 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001461#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001462 /* setbpt/clearbpt never used: */
1463 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001464#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001465 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001466 switch (new) {
1467 case 2:
1468 break; /* x86 SYS_fork */
1469 case SYS_clone:
1470 new = 120;
1471 break;
1472 default:
1473 fprintf(stderr, "%s: unexpected syscall %d\n",
1474 __FUNCTION__, new);
1475 return -1;
1476 }
1477 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1478 return -1;
1479 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1480 return -1;
1481 return 0;
1482#elif defined(HPPA)
1483 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1484 return -1;
1485 return 0;
1486#elif defined(SH)
1487 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1488 return -1;
1489 return 0;
1490#elif defined(SH64)
1491 /* Top half of reg encodes the no. of args n as 0x1n.
1492 Assume 0 args as kernel never actually checks... */
1493 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1494 0x100000 | new) < 0)
1495 return -1;
1496 return 0;
1497#elif defined(CRISV10) || defined(CRISV32)
1498 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1499 return -1;
1500 return 0;
1501#elif defined(ARM)
1502 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1503# ifndef PTRACE_SET_SYSCALL
1504# define PTRACE_SET_SYSCALL 23
1505# endif
1506 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1507 return -1;
1508 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001509#elif defined(AARCH64)
1510 /* setbpt/clearbpt never used: */
1511 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001512#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001513 /* setbpt/clearbpt never used: */
1514 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001515#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001516 /* setbpt/clearbpt never used: */
1517 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001518#elif defined(OR1K)
1519 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001520#elif defined(METAG)
1521 /* setbpt/clearbpt never used: */
1522 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001523#elif defined(XTENSA)
1524 /* setbpt/clearbpt never used: */
1525 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301526#elif defined(ARC)
1527 /* setbpt/clearbpt never used: */
1528 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001529#else
1530#warning Do not know how to handle change_syscall for this architecture
1531#endif /* architecture */
1532 return -1;
1533}
1534
Roland McGrathd81f1d92003-01-09 06:53:34 +00001535int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001536setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001537{
Roland McGrath3291ef22008-05-20 00:34:34 +00001538 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001539 arg_setup_state state;
1540
1541 if (tcp->flags & TCB_BPTSET) {
1542 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1543 return -1;
1544 }
1545
Roland McGrath3291ef22008-05-20 00:34:34 +00001546 /*
1547 * It's a silly kludge to initialize this with a search at runtime.
1548 * But it's better than maintaining another magic thing in the
1549 * godforsaken tables.
1550 */
1551 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001552 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001553 for (i = 0; i < nsyscalls; ++i)
1554 if (sysent[i].sys_func == sys_clone) {
1555 clone_scno[current_personality] = i;
1556 break;
1557 }
1558 }
1559
Dmitry V. Levin65563152014-05-12 13:43:10 +00001560 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001561 if (arg_setup(tcp, &state) < 0
1562 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1563 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001564 || change_syscall(tcp, &state,
1565 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001566 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1567 || set_arg1(tcp, &state, 0) < 0
1568 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001569 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001570 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1571 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001572 tcp->flags |= TCB_BPTSET;
1573 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001574 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001575
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001576 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001577 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001578 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001579 vfork semantics into plain fork - each application must not
1580 depend on the vfork specifics according to POSIX. We would
1581 hang waiting for the parent resume otherwise. We need to
1582 clear also CLONE_VM but only in the CLONE_VFORK case as
1583 otherwise we would break pthread_create. */
1584
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001585 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1586 if (new_arg0 & CLONE_VFORK)
1587 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1588 if (arg_setup(tcp, &state) < 0
1589 || set_arg0(tcp, &state, new_arg0) < 0
1590 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001591 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001592 tcp->inst[0] = tcp->u_arg[arg0_index];
1593 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001594 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001595 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001596 }
1597
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001598 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1599 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001600 return -1;
1601}
1602
1603int
Denys Vlasenko12014262011-05-30 14:00:14 +02001604clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001605{
1606 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001607 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001608 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001609 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1610 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1611 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001612 if (errno != ESRCH)
1613 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001614 tcp->flags &= ~TCB_BPTSET;
1615 return 0;
1616}