blob: 4e62a8aa7585c4d777bb87881070b9e43968429a [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>
John Hughes1d08dcf2001-07-10 13:48:44 +000038#if HAVE_SYS_UIO_H
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010039# include <sys/uio.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000040#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000041
Denys Vlasenko84703742012-02-25 02:38:52 +010042#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000043# include <asm/ptrace_offsets.h>
44# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000045#endif
46
Wichert Akkerman36915a11999-07-13 15:45:02 +000047#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010048# include <sys/reg.h>
Wichert Akkermanfaf72222000-02-19 23:59:03 +000049#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010050# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000051# ifdef HAVE_STRUCT_IA64_FPREG
52# define ia64_fpreg XXX_ia64_fpreg
53# endif
54# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
55# define pt_all_user_regs XXX_pt_all_user_regs
56# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030057# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
58# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
59# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010060# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030061# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000062# undef ia64_fpreg
63# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000064#endif
65
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000066int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000067string_to_uint(const char *str)
68{
69 char *error;
70 long value;
71
72 if (!*str)
73 return -1;
74 errno = 0;
75 value = strtol(str, &error, 10);
76 if (errno || *error || value < 0 || (long)(int)value != value)
77 return -1;
78 return (int)value;
79}
80
81int
Dmitry V. Levin447db452014-05-29 17:59:01 +000082tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083{
84 return a->tv_sec || a->tv_usec;
85}
86
87int
Dmitry V. Levin447db452014-05-29 17:59:01 +000088tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089{
90 if (a->tv_sec < b->tv_sec
91 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
92 return -1;
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 return 0;
97}
98
99double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000100tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101{
102 return tv->tv_sec + tv->tv_usec/1000000.0;
103}
104
105void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000106tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107{
108 tv->tv_sec = a->tv_sec + b->tv_sec;
109 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000110 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111 tv->tv_sec++;
112 tv->tv_usec -= 1000000;
113 }
114}
115
116void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000117tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118{
119 tv->tv_sec = a->tv_sec - b->tv_sec;
120 tv->tv_usec = a->tv_usec - b->tv_usec;
121 if (((long) tv->tv_usec) < 0) {
122 tv->tv_sec--;
123 tv->tv_usec += 1000000;
124 }
125}
126
127void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000128tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129{
130 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
131 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
132 tv->tv_usec %= 1000000;
133}
134
135void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000136tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137{
138 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000139 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140 tv->tv_usec %= 1000000;
141}
142
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000143const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000144xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145{
146 for (; xlat->str != NULL; xlat++)
147 if (xlat->val == val)
148 return xlat->str;
149 return NULL;
150}
151
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000152static int
153xlat_bsearch_compare(const void *a, const void *b)
154{
155 const unsigned int val1 = (const unsigned long) a;
156 const unsigned int val2 = ((const struct xlat *) b)->val;
157 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
158}
159
160const char *
161xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
162{
163 const struct xlat *e =
164 bsearch((const void*) (const unsigned long) val,
165 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
166
167 return e ? e->str : NULL;
168}
169
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200170#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200171char *
172stpcpy(char *dst, const char *src)
173{
174 while ((*dst = *src++) != '\0')
175 dst++;
176 return dst;
177}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200178#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200179
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100180/* Find a next bit which is set.
181 * Starts testing at cur_bit.
182 * Returns -1 if no more bits are set.
183 *
184 * We never touch bytes we don't need to.
185 * On big-endian, array is assumed to consist of
186 * current_wordsize wide words: for example, is current_wordsize is 4,
187 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
188 * On little-endian machines, word size is immaterial.
189 */
190int
191next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
192{
193 const unsigned endian = 1;
194 int little_endian = *(char*)&endian;
195
196 const uint8_t *array = bit_array;
197 unsigned pos = cur_bit / 8;
198 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
199
200 for (;;) {
201 uint8_t bitmask;
202 uint8_t cur_byte;
203
204 if (cur_bit >= size_bits)
205 return -1;
206 cur_byte = array[pos ^ pos_xor_mask];
207 if (cur_byte == 0) {
208 cur_bit = (cur_bit + 8) & (-8);
209 pos++;
210 continue;
211 }
212 bitmask = 1 << (cur_bit & 7);
213 for (;;) {
214 if (cur_byte & bitmask)
215 return cur_bit;
216 cur_bit++;
217 if (cur_bit >= size_bits)
218 return -1;
219 bitmask <<= 1;
220 /* This check *can't be* optimized out: */
221 if (bitmask == 0)
222 break;
223 }
224 pos++;
225 }
226}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227/*
228 * Print entry in struct xlat table, if there.
229 */
230void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000231printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000233 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234
235 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200236 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 else
238 tprintf("%#x /* %s */", val, dflt);
239}
240
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100241/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100242 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100243 * argument.
244 */
245int
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000246printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100247{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000248#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
249# if SUPPORTED_PERSONALITIES > 1
250 if (current_wordsize > 4) {
251# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100252 tprintf(format, tcp->u_arg[arg_no]);
253 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000254# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100255 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000256# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000257 /* Align arg_no to the next even number. */
258 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000259# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100260 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
261 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100262 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000263# endif /* SUPPORTED_PERSONALITIES */
264#elif SIZEOF_LONG > 4
265# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
266#elif defined LINUX_MIPSN32
267 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100268 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000269#elif defined X32
270 if (current_personality == 0) {
271 tprintf(format, tcp->ext_arg[arg_no]);
272 arg_no++;
273 } else {
274 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
275 arg_no += 2;
276 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100277#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000278# if defined __ARM_EABI__ || \
279 defined LINUX_MIPSO32 || \
280 defined POWERPC || \
281 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000282 /* Align arg_no to the next even number. */
283 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000284# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100285 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
286 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100287#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000288
Chris Metcalf879dddd2013-03-01 10:41:02 +0100289 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100290}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100291
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000292/*
293 * Interpret `xlat' as an array of flags
294 * print the entries whose bits are on in `flags'
295 * return # of flags printed.
296 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200297void
Denys Vlasenko12014262011-05-30 14:00:14 +0200298addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200300 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301 if (xlat->val && (flags & xlat->val) == xlat->val) {
302 tprintf("|%s", xlat->str);
303 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304 }
305 }
306 if (flags) {
307 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309}
310
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000311/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200312 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000313 * Print to static string the entries whose bits are on in `flags'
314 * Return static string.
315 */
316const char *
317sprintflags(const char *prefix, const struct xlat *xlat, int flags)
318{
319 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200320 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000321 int found = 0;
322
Denys Vlasenko52845572011-08-31 12:07:38 +0200323 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000324
325 for (; xlat->str; xlat++) {
326 if ((flags & xlat->val) == xlat->val) {
327 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200328 *outptr++ = '|';
329 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000330 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100331 flags &= ~xlat->val;
332 if (!flags)
333 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000334 }
335 }
336 if (flags) {
337 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200338 *outptr++ = '|';
339 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000340 }
341
342 return outstr;
343}
344
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000346printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000347{
348 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000349 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350
351 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200352 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353 return 1;
354 }
355
356 sep = "";
357 for (n = 0; xlat->str; xlat++) {
358 if (xlat->val && (flags & xlat->val) == xlat->val) {
359 tprintf("%s%s", sep, xlat->str);
360 flags &= ~xlat->val;
361 sep = "|";
362 n++;
363 }
364 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000365
366 if (n) {
367 if (flags) {
368 tprintf("%s%#x", sep, flags);
369 n++;
370 }
371 } else {
372 if (flags) {
373 tprintf("%#x", flags);
374 if (dflt)
375 tprintf(" /* %s */", dflt);
376 } else {
377 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200378 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000379 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000381
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382 return n;
383}
384
385void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000386printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387{
Roland McGratheb285352003-01-14 09:59:00 +0000388 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389
390 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200391 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 return;
393 }
394 if (umove(tcp, addr, &num) < 0) {
395 tprintf("%#lx", addr);
396 return;
397 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200398 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000399 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200400 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000401}
402
Roland McGrath6bc12202003-11-13 22:32:27 +0000403void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000404printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000405{
406 int num;
407
408 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200409 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000410 return;
411 }
412 if (umove(tcp, addr, &num) < 0) {
413 tprintf("%#lx", addr);
414 return;
415 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200416 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000417 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200418 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000419}
420
421void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300422printfd(struct tcb *tcp, int fd)
423{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100424 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000425 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
426 static const char socket_prefix[] = "socket:[";
427 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
428 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000429
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000430 if (show_fd_path > 1 &&
431 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
432 path[(path_len = strlen(path)) - 1] == ']') {
433 unsigned long inodenr;
434 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
435 tprintf("%d<", fd);
436 if (!print_sockaddr_by_inode(inodenr))
437 tprints(path);
438 tprints(">");
439 } else {
440 tprintf("%d<%s>", fd, path);
441 }
442 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000443 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300444}
445
446void
Denys Vlasenko12014262011-05-30 14:00:14 +0200447printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000448{
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000449 tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000450}
451
Dmitry V. Levina501f142008-11-10 23:19:13 +0000452/*
453 * Quote string `instr' of length `size'
454 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200455 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000456 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100457 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200458 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100459 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000460 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400461int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200462string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000464 const unsigned char *ustr = (const unsigned char *) instr;
465 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200466 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000467
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200468 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200469 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200470 size--;
471 eol = '\0';
472 }
473
474 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000475 if (xflag > 1)
476 usehex = 1;
477 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000478 /* Check for presence of symbol which require
479 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000480 for (i = 0; i < size; ++i) {
481 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000482 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200483 if (c == eol)
484 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100485
486 /* Force hex unless c is printable or whitespace */
487 if (c > 0x7e) {
488 usehex = 1;
489 break;
490 }
491 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
492 * They happen to have ASCII codes 9,10,11,12,13.
493 */
494 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000495 usehex = 1;
496 break;
497 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 }
499 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000500
501 *s++ = '\"';
502
503 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000504 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000505 for (i = 0; i < size; ++i) {
506 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000507 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200508 if (c == eol)
509 goto asciz_ended;
510 *s++ = '\\';
511 *s++ = 'x';
512 *s++ = "0123456789abcdef"[c >> 4];
513 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000514 }
515 } else {
516 for (i = 0; i < size; ++i) {
517 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000518 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200519 if (c == eol)
520 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000521 switch (c) {
522 case '\"': case '\\':
523 *s++ = '\\';
524 *s++ = c;
525 break;
526 case '\f':
527 *s++ = '\\';
528 *s++ = 'f';
529 break;
530 case '\n':
531 *s++ = '\\';
532 *s++ = 'n';
533 break;
534 case '\r':
535 *s++ = '\\';
536 *s++ = 'r';
537 break;
538 case '\t':
539 *s++ = '\\';
540 *s++ = 't';
541 break;
542 case '\v':
543 *s++ = '\\';
544 *s++ = 'v';
545 break;
546 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100547 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000548 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200549 else {
550 /* Print \octal */
551 *s++ = '\\';
552 if (i + 1 < size
553 && ustr[i + 1] >= '0'
554 && ustr[i + 1] <= '9'
555 ) {
556 /* Print \ooo */
557 *s++ = '0' + (c >> 6);
558 *s++ = '0' + ((c >> 3) & 0x7);
559 } else {
560 /* Print \[[o]o]o */
561 if ((c >> 3) != 0) {
562 if ((c >> 6) != 0)
563 *s++ = '0' + (c >> 6);
564 *s++ = '0' + ((c >> 3) & 0x7);
565 }
566 }
567 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000568 }
569 break;
570 }
571 }
572 }
573
574 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000576
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200577 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200578 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200579 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
580 * but next char is NUL.
581 */
582 return 0;
583 }
584
585 return 1;
586
587 asciz_ended:
588 *s++ = '\"';
589 *s = '\0';
590 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
591 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592}
593
Dmitry V. Levina501f142008-11-10 23:19:13 +0000594/*
595 * Print path string specified by address `addr' and length `n'.
596 * If path length exceeds `n', append `...' to the output.
597 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000599printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100601 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100602 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100603
Dmitry V. Levina501f142008-11-10 23:19:13 +0000604 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200605 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000606 return;
607 }
608
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100609 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000610 if (n > sizeof path - 1)
611 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000612
613 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100614 nul_seen = umovestr(tcp, addr, n + 1, path);
615 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000616 tprintf("%#lx", addr);
617 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100618 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000619
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100620 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100621 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100622 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100623 string_quote(path, outstr, -1, n);
624 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100625 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100626 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627 }
628}
629
630void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000631printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100633 /* Size must correspond to char path[] size in printpathn */
634 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000635}
636
Dmitry V. Levina501f142008-11-10 23:19:13 +0000637/*
638 * Print string specified by address `addr' and length `len'.
639 * If `len' < 0, treat the string as a NUL-terminated string.
640 * If string length exceeds `max_strlen', append `...' to the output.
641 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000642void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200643printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000644{
645 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000646 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000647 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100648 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649
650 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200651 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652 return;
653 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000654 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200655 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000656 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
657
658 if (outstr_size / 4 != max_strlen)
659 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000660 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200661 if (!str)
662 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000663 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200664 if (!outstr)
665 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000667
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200668 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000669 /*
670 * Treat as a NUL-terminated string: fetch one byte more
671 * because string_quote() quotes one byte less.
672 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000673 size = max_strlen + 1;
674 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675 tprintf("%#lx", addr);
676 return;
677 }
678 }
679 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200680 size = max_strlen;
681 if (size > (unsigned long)len)
682 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000683 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 tprintf("%#lx", addr);
685 return;
686 }
687 }
688
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100689 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
690 * or we were requested to print more than -s NUM chars)...
691 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100692 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000693 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000694
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100695 tprints(outstr);
696 if (ellipsis)
697 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698}
699
John Hughes1d08dcf2001-07-10 13:48:44 +0000700#if HAVE_SYS_UIO_H
701void
Denys Vlasenko12014262011-05-30 14:00:14 +0200702dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000703{
Denys Vlasenko84703742012-02-25 02:38:52 +0100704#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000705 union {
706 struct { u_int32_t base; u_int32_t len; } *iov32;
707 struct { u_int64_t base; u_int64_t len; } *iov64;
708 } iovu;
709#define iov iovu.iov64
710#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100711 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000712#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100713 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000714#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100715 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000716#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000717 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000718#define sizeof_iov sizeof(*iov)
719#define iov_iov_base(i) iov[i].iov_base
720#define iov_iov_len(i) iov[i].iov_len
721#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000722 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200723 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000724
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200725 size = sizeof_iov * len;
726 /* Assuming no sane program has millions of iovs */
727 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000728 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200729 fprintf(stderr, "Out of memory\n");
730 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000731 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000732 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000733 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000734 /* include the buffer number to make it easy to
735 * match up the trace with the source */
736 tprintf(" * %lu bytes in buffer %d\n",
737 (unsigned long)iov_iov_len(i), i);
738 dumpstr(tcp, (long) iov_iov_base(i),
739 iov_iov_len(i));
740 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000741 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200742 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000743#undef sizeof_iov
744#undef iov_iov_base
745#undef iov_iov_len
746#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000747}
748#endif
749
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750void
Denys Vlasenko12014262011-05-30 14:00:14 +0200751dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752{
753 static int strsize = -1;
754 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000755
Denys Vlasenko76325802013-02-22 14:47:39 +0100756 char outbuf[
757 (
758 (sizeof(
759 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
760 "1234567890123456") + /*in case I'm off by few:*/ 4)
761 /*align to 8 to make memset easier:*/ + 7) & -8
762 ];
763 const unsigned char *src;
764 int i;
765
766 memset(outbuf, ' ', sizeof(outbuf));
767
768 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200769 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100770 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200771 if (!str) {
772 strsize = -1;
773 fprintf(stderr, "Out of memory\n");
774 return;
775 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100776 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 }
778
779 if (umoven(tcp, addr, len, (char *) str) < 0)
780 return;
781
Denys Vlasenko76325802013-02-22 14:47:39 +0100782 /* Space-pad to 16 bytes */
783 i = len;
784 while (i & 0xf)
785 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200786
Denys Vlasenko76325802013-02-22 14:47:39 +0100787 i = 0;
788 src = str;
789 while (i < len) {
790 char *dst = outbuf;
791 /* Hex dump */
792 do {
793 if (i < len) {
794 *dst++ = "0123456789abcdef"[*src >> 4];
795 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 }
797 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100798 *dst++ = ' ';
799 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100801 dst++; /* space is there by memset */
802 i++;
803 if ((i & 7) == 0)
804 dst++; /* space is there by memset */
805 src++;
806 } while (i & 0xf);
807 /* ASCII dump */
808 i -= 16;
809 src -= 16;
810 do {
811 if (*src >= ' ' && *src < 0x7f)
812 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100814 *dst++ = '.';
815 src++;
816 } while (++i & 0xf);
817 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100818 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 }
820}
821
Mike Frysinger612659e2012-02-14 14:38:28 +0100822#ifdef HAVE_PROCESS_VM_READV
823/* C library supports this, but the kernel might not. */
824static bool process_vm_readv_not_supported = 0;
825#else
826
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100827/* Need to do this since process_vm_readv() is not yet available in libc.
828 * When libc is be updated, only "static bool process_vm_readv_not_supported"
829 * line should remain.
830 */
831#if !defined(__NR_process_vm_readv)
832# if defined(I386)
833# define __NR_process_vm_readv 347
834# elif defined(X86_64)
835# define __NR_process_vm_readv 310
836# elif defined(POWERPC)
837# define __NR_process_vm_readv 351
838# endif
839#endif
840
841#if defined(__NR_process_vm_readv)
842static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400843/* Have to avoid duplicating with the C library headers. */
844static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100845 const struct iovec *lvec,
846 unsigned long liovcnt,
847 const struct iovec *rvec,
848 unsigned long riovcnt,
849 unsigned long flags)
850{
851 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
852}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400853#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100854#else
855static bool process_vm_readv_not_supported = 1;
856# define process_vm_readv(...) (errno = ENOSYS, -1)
857#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100858
859#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100860
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000861#define PAGMASK (~(PAGSIZ - 1))
862/*
863 * move `len' bytes of data from process `pid'
864 * at address `addr' to our space at `laddr'
865 */
866int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000867umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700869 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000870 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871 union {
872 long val;
873 char x[sizeof(long)];
874 } u;
875
Denys Vlasenko2544f982013-02-19 17:39:56 +0100876#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100877 if (current_wordsize < sizeof(addr))
878 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100879#endif
880
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100881 if (!process_vm_readv_not_supported) {
882 struct iovec local[1], remote[1];
883 int r;
884
885 local[0].iov_base = laddr;
886 remote[0].iov_base = (void*)addr;
887 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000888 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100889 if (r == len)
890 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000891 if (r >= 0) {
892 error_msg("umoven: short read (%d < %d) @0x%lx",
893 r, len, addr);
894 return -1;
895 }
896 switch (errno) {
897 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100898 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000899 break;
900 case ESRCH:
901 /* the process is gone */
902 return -1;
903 case EFAULT: case EIO: case EPERM:
904 /* address space is inaccessible */
905 return -1;
906 default:
907 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100908 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000909 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100910 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100911 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100912
Dmitry V. Levin97005922013-02-26 21:16:22 +0000913 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914 if (addr & (sizeof(long) - 1)) {
915 /* addr not a multiple of sizeof(long) */
916 n = addr - (addr & -sizeof(long)); /* residue */
917 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700918 errno = 0;
919 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000920 switch (errno) {
921 case 0:
922 break;
923 case ESRCH: case EINVAL:
924 /* these could be seen if the process is gone */
925 return -1;
926 case EFAULT: case EIO: case EPERM:
927 /* address space is inaccessible */
928 return -1;
929 default:
930 /* all the rest is strange and should be reported */
931 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
932 pid, addr);
933 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700934 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100935 m = MIN(sizeof(long) - n, len);
936 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100937 addr += sizeof(long);
938 laddr += m;
939 nread += m;
940 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 }
942 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700943 errno = 0;
944 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000945 switch (errno) {
946 case 0:
947 break;
948 case ESRCH: case EINVAL:
949 /* these could be seen if the process is gone */
950 return -1;
951 case EFAULT: case EIO: case EPERM:
952 /* address space is inaccessible */
953 if (nread) {
954 perror_msg("umoven: short read (%d < %d) @0x%lx",
955 nread, nread + len, addr - nread);
956 }
957 return -1;
958 default:
959 /* all the rest is strange and should be reported */
960 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
961 pid, addr);
962 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700963 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100964 m = MIN(sizeof(long), len);
965 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100966 addr += sizeof(long);
967 laddr += m;
968 nread += m;
969 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 return 0;
973}
974
975/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100976 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100978 *
979 * Returns < 0 on error, > 0 if NUL was seen,
980 * (TODO if useful: return count of bytes including NUL),
981 * else 0 if len bytes were read but no NUL byte seen.
982 *
983 * Note: there is no guarantee we won't overwrite some bytes
984 * in laddr[] _after_ terminating NUL (but, of course,
985 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 */
987int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000988umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989{
Denys Vlasenko16940922013-03-01 18:52:59 +0100990#if SIZEOF_LONG == 4
991 const unsigned long x01010101 = 0x01010101ul;
992 const unsigned long x80808080 = 0x80808080ul;
993#elif SIZEOF_LONG == 8
994 const unsigned long x01010101 = 0x0101010101010101ul;
995 const unsigned long x80808080 = 0x8080808080808080ul;
996#else
997# error SIZEOF_LONG > 8
998#endif
999
Roland McGratheb9e2e82009-06-02 16:49:22 -07001000 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +01001001 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001003 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 char x[sizeof(long)];
1005 } u;
1006
Denys Vlasenko2544f982013-02-19 17:39:56 +01001007#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001008 if (current_wordsize < sizeof(addr))
1009 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001010#endif
1011
Dmitry V. Levin97005922013-02-26 21:16:22 +00001012 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001013 if (!process_vm_readv_not_supported) {
1014 struct iovec local[1], remote[1];
1015
1016 local[0].iov_base = laddr;
1017 remote[0].iov_base = (void*)addr;
1018
1019 while (len > 0) {
1020 int end_in_page;
1021 int r;
1022 int chunk_len;
1023
1024 /* Don't read kilobytes: most strings are short */
1025 chunk_len = len;
1026 if (chunk_len > 256)
1027 chunk_len = 256;
1028 /* Don't cross pages. I guess otherwise we can get EFAULT
1029 * and fail to notice that terminating NUL lies
1030 * in the existing (first) page.
1031 * (I hope there aren't arches with pages < 4K)
1032 */
1033 end_in_page = ((addr + chunk_len) & 4095);
1034 r = chunk_len - end_in_page;
1035 if (r > 0) /* if chunk_len > end_in_page */
1036 chunk_len = r; /* chunk_len -= end_in_page */
1037
1038 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001039 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1040 if (r > 0) {
1041 if (memchr(local[0].iov_base, '\0', r))
1042 return 1;
1043 local[0].iov_base += r;
1044 remote[0].iov_base += r;
1045 len -= r;
1046 nread += r;
1047 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001048 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001049 switch (errno) {
1050 case ENOSYS:
1051 process_vm_readv_not_supported = 1;
1052 goto vm_readv_didnt_work;
1053 case ESRCH:
1054 /* the process is gone */
1055 return -1;
1056 case EFAULT: case EIO: case EPERM:
1057 /* address space is inaccessible */
1058 if (nread) {
1059 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1060 nread, nread + len, addr);
1061 }
1062 return -1;
1063 default:
1064 /* all the rest is strange and should be reported */
1065 perror_msg("process_vm_readv");
1066 return -1;
1067 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001068 }
1069 return 0;
1070 }
1071 vm_readv_didnt_work:
1072
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 if (addr & (sizeof(long) - 1)) {
1074 /* addr not a multiple of sizeof(long) */
1075 n = addr - (addr & -sizeof(long)); /* residue */
1076 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001077 errno = 0;
1078 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001079 switch (errno) {
1080 case 0:
1081 break;
1082 case ESRCH: case EINVAL:
1083 /* these could be seen if the process is gone */
1084 return -1;
1085 case EFAULT: case EIO: case EPERM:
1086 /* address space is inaccessible */
1087 return -1;
1088 default:
1089 /* all the rest is strange and should be reported */
1090 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1091 pid, addr);
1092 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001093 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001094 m = MIN(sizeof(long) - n, len);
1095 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 while (n & (sizeof(long) - 1))
1097 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001098 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001099 addr += sizeof(long);
1100 laddr += m;
1101 nread += m;
1102 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001104
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001106 errno = 0;
1107 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001108 switch (errno) {
1109 case 0:
1110 break;
1111 case ESRCH: case EINVAL:
1112 /* these could be seen if the process is gone */
1113 return -1;
1114 case EFAULT: case EIO: case EPERM:
1115 /* address space is inaccessible */
1116 if (nread) {
1117 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1118 nread, nread + len, addr - nread);
1119 }
1120 return -1;
1121 default:
1122 /* all the rest is strange and should be reported */
1123 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1124 pid, addr);
1125 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001126 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001127 m = MIN(sizeof(long), len);
1128 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001129 /* "If a NUL char exists in this word" */
1130 if ((u.val - x01010101) & ~u.val & x80808080)
1131 return 1;
1132 addr += sizeof(long);
1133 laddr += m;
1134 nread += m;
1135 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001137 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138}
1139
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001141upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142{
1143 long val;
1144
Roland McGratheb9e2e82009-06-02 16:49:22 -07001145 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001146 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001147 if (val == -1 && errno) {
1148 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001149 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001150 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001152 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 *res = val;
1154 return 0;
1155}
1156
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001157/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1158 * and PTRACE_O_TRACE[V]FORK for tracing children.
1159 * If you are adding a new arch which is only supported by newer kernels,
1160 * you most likely don't need to add any code below
1161 * beside a dummy "return 0" block in change_syscall().
1162 */
1163
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001164/*
1165 * These #if's are huge, please indent them correctly.
1166 * It's easy to get confused otherwise.
1167 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001169#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001170
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001171#ifndef CLONE_PTRACE
1172# define CLONE_PTRACE 0x00002000
1173#endif
1174#ifndef CLONE_VFORK
1175# define CLONE_VFORK 0x00004000
1176#endif
1177#ifndef CLONE_VM
1178# define CLONE_VM 0x00000100
1179#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001181#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182
1183typedef unsigned long *arg_setup_state;
1184
1185static int
1186arg_setup(struct tcb *tcp, arg_setup_state *state)
1187{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001188 unsigned long cfm, sof, sol;
1189 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001190
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001191 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001192 /* Satisfy a false GCC warning. */
1193 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001194 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001195 }
Roland McGrath08267b82004-02-20 22:56:43 +00001196
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001197 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001198 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001199 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001200 return -1;
1201
1202 sof = (cfm >> 0) & 0x7f;
1203 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001204 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001205
Jan Kratochvil1f942712008-08-06 21:38:52 +00001206 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001207 return 0;
1208}
1209
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001210# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211
Roland McGrathd81f1d92003-01-09 06:53:34 +00001212static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001213get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214{
Roland McGrath08267b82004-02-20 22:56:43 +00001215 int ret;
1216
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001217 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001218 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001219 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001220 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001221 (unsigned long) ia64_rse_skip_regs(*state, 0),
1222 sizeof(long), (void *) valp);
1223 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001224}
1225
1226static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001227get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001228{
Roland McGrath08267b82004-02-20 22:56:43 +00001229 int ret;
1230
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001231 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001232 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001233 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001234 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001235 (unsigned long) ia64_rse_skip_regs(*state, 1),
1236 sizeof(long), (void *) valp);
1237 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001238}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001239
1240static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001241set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001242{
Roland McGrath08267b82004-02-20 22:56:43 +00001243 int req = PTRACE_POKEDATA;
1244 void *ap;
1245
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001246 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001247 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1248 req = PTRACE_POKEUSER;
1249 } else
1250 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001251 errno = 0;
1252 ptrace(req, tcp->pid, ap, val);
1253 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254}
1255
1256static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001257set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001258{
Roland McGrath08267b82004-02-20 22:56:43 +00001259 int req = PTRACE_POKEDATA;
1260 void *ap;
1261
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001262 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001263 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1264 req = PTRACE_POKEUSER;
1265 } else
1266 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001267 errno = 0;
1268 ptrace(req, tcp->pid, ap, val);
1269 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270}
1271
Roland McGrathb659f872008-07-18 01:19:36 +00001272/* ia64 does not return the input arguments from functions (and syscalls)
1273 according to ia64 RSE (Register Stack Engine) behavior. */
1274
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001275# define restore_arg0(tcp, state, val) ((void) (state), 0)
1276# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001277
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001278#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001280# if defined(SPARC64)
1281# undef PTRACE_GETREGS
1282# define PTRACE_GETREGS PTRACE_GETREGS64
1283# undef PTRACE_SETREGS
1284# define PTRACE_SETREGS PTRACE_SETREGS64
1285# endif
1286
Mike Frysinger8566c502009-10-12 11:05:14 -04001287typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001288
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001289# define arg_setup(tcp, state) \
1290 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1291# define arg_finish_change(tcp, state) \
1292 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001293
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001294# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1295# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1296# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1297# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1298# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001300#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001302# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001303/* Note: this is only true for the `clone' system call, which handles
1304 arguments specially. We could as well say that its first two arguments
1305 are swapped relative to other architectures, but that would just be
1306 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001307# define arg0_offset PT_GPR3
1308# define arg1_offset PT_ORIGGPR2
1309# define restore_arg0(tcp, state, val) ((void) (state), 0)
1310# define restore_arg1(tcp, state, val) ((void) (state), 0)
1311# define arg0_index 1
1312# define arg1_index 0
1313# elif defined(ALPHA) || defined(MIPS)
1314# define arg0_offset REG_A0
1315# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001316# elif defined(POWERPC)
1317# define arg0_offset (sizeof(unsigned long)*PT_R3)
1318# define arg1_offset (sizeof(unsigned long)*PT_R4)
1319# define restore_arg0(tcp, state, val) ((void) (state), 0)
1320# elif defined(HPPA)
1321# define arg0_offset PT_GR26
1322# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001323# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001324# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1325# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1326# elif defined(SH)
1327# define arg0_offset (4*(REG_REG0+4))
1328# define arg1_offset (4*(REG_REG0+5))
1329# elif defined(SH64)
1330 /* ABI defines arg0 & 1 in r2 & r3 */
1331# define arg0_offset (REG_OFFSET+16)
1332# define arg1_offset (REG_OFFSET+24)
1333# define restore_arg0(tcp, state, val) 0
1334# elif defined CRISV10 || defined CRISV32
1335# define arg0_offset (4*PT_R11)
1336# define arg1_offset (4*PT_ORIG_R10)
1337# define restore_arg0(tcp, state, val) 0
1338# define restore_arg1(tcp, state, val) 0
1339# define arg0_index 1
1340# define arg1_index 0
1341# else
1342# define arg0_offset 0
1343# define arg1_offset 4
1344# if defined ARM
1345# define restore_arg0(tcp, state, val) 0
1346# endif
1347# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348
1349typedef int arg_setup_state;
1350
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001351# define arg_setup(tcp, state) (0)
1352# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001353# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1354# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355
1356static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001357set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001359 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360}
1361
1362static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001363set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001364{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001365 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366}
1367
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001368#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001369
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001370#ifndef restore_arg0
1371# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1372#endif
1373#ifndef restore_arg1
1374# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1375#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001376
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001377#ifndef arg0_index
1378# define arg0_index 0
1379# define arg1_index 1
1380#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001381
James Hogan05eb9052012-11-29 17:37:37 +00001382static int
1383change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1384{
1385#if defined(I386)
1386 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1387 return -1;
1388 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001389#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001390 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1391 return -1;
1392 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001393#elif defined(X32)
1394 /* setbpt/clearbpt never used: */
1395 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001396#elif defined(POWERPC)
1397 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1398 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1399 return -1;
1400 return 0;
1401#elif defined(S390) || defined(S390X)
1402 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1403 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1404 return -1;
1405 return 0;
1406#elif defined(M68K)
1407 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1408 return -1;
1409 return 0;
1410#elif defined(SPARC) || defined(SPARC64)
1411 state->u_regs[U_REG_G1] = new;
1412 return 0;
1413#elif defined(MIPS)
1414 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1415 return -1;
1416 return 0;
1417#elif defined(ALPHA)
1418 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1419 return -1;
1420 return 0;
1421#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001422 /* setbpt/clearbpt never used: */
1423 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001424#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001425 /* setbpt/clearbpt never used: */
1426 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001427#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001428 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001429 switch (new) {
1430 case 2:
1431 break; /* x86 SYS_fork */
1432 case SYS_clone:
1433 new = 120;
1434 break;
1435 default:
1436 fprintf(stderr, "%s: unexpected syscall %d\n",
1437 __FUNCTION__, new);
1438 return -1;
1439 }
1440 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1441 return -1;
1442 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1443 return -1;
1444 return 0;
1445#elif defined(HPPA)
1446 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1447 return -1;
1448 return 0;
1449#elif defined(SH)
1450 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1451 return -1;
1452 return 0;
1453#elif defined(SH64)
1454 /* Top half of reg encodes the no. of args n as 0x1n.
1455 Assume 0 args as kernel never actually checks... */
1456 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1457 0x100000 | new) < 0)
1458 return -1;
1459 return 0;
1460#elif defined(CRISV10) || defined(CRISV32)
1461 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1462 return -1;
1463 return 0;
1464#elif defined(ARM)
1465 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1466# ifndef PTRACE_SET_SYSCALL
1467# define PTRACE_SET_SYSCALL 23
1468# endif
1469 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1470 return -1;
1471 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001472#elif defined(AARCH64)
1473 /* setbpt/clearbpt never used: */
1474 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001475#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001476 /* setbpt/clearbpt never used: */
1477 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001478#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001479 /* setbpt/clearbpt never used: */
1480 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001481#elif defined(OR1K)
1482 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001483#elif defined(METAG)
1484 /* setbpt/clearbpt never used: */
1485 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001486#elif defined(XTENSA)
1487 /* setbpt/clearbpt never used: */
1488 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301489#elif defined(ARC)
1490 /* setbpt/clearbpt never used: */
1491 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001492#else
1493#warning Do not know how to handle change_syscall for this architecture
1494#endif /* architecture */
1495 return -1;
1496}
1497
Roland McGrathd81f1d92003-01-09 06:53:34 +00001498int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001499setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001500{
Roland McGrath3291ef22008-05-20 00:34:34 +00001501 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001502 arg_setup_state state;
1503
1504 if (tcp->flags & TCB_BPTSET) {
1505 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1506 return -1;
1507 }
1508
Roland McGrath3291ef22008-05-20 00:34:34 +00001509 /*
1510 * It's a silly kludge to initialize this with a search at runtime.
1511 * But it's better than maintaining another magic thing in the
1512 * godforsaken tables.
1513 */
1514 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001515 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001516 for (i = 0; i < nsyscalls; ++i)
1517 if (sysent[i].sys_func == sys_clone) {
1518 clone_scno[current_personality] = i;
1519 break;
1520 }
1521 }
1522
Dmitry V. Levin65563152014-05-12 13:43:10 +00001523 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001524 if (arg_setup(tcp, &state) < 0
1525 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1526 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001527 || change_syscall(tcp, &state,
1528 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001529 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1530 || set_arg1(tcp, &state, 0) < 0
1531 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001532 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001533 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1534 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001535 tcp->flags |= TCB_BPTSET;
1536 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001537 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001538
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001539 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001540 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001541 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001542 vfork semantics into plain fork - each application must not
1543 depend on the vfork specifics according to POSIX. We would
1544 hang waiting for the parent resume otherwise. We need to
1545 clear also CLONE_VM but only in the CLONE_VFORK case as
1546 otherwise we would break pthread_create. */
1547
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001548 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1549 if (new_arg0 & CLONE_VFORK)
1550 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1551 if (arg_setup(tcp, &state) < 0
1552 || set_arg0(tcp, &state, new_arg0) < 0
1553 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001554 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001555 tcp->inst[0] = tcp->u_arg[arg0_index];
1556 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001557 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001558 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001559 }
1560
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001561 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1562 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001563 return -1;
1564}
1565
1566int
Denys Vlasenko12014262011-05-30 14:00:14 +02001567clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001568{
1569 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001570 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001571 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001572 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1573 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1574 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001575 if (errno != ESRCH)
1576 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001577 tcp->flags &= ~TCB_BPTSET;
1578 return 0;
1579}