blob: b13f3dc61e3f1476de89a4455e96c696f9209873 [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>
Maarten ter Huurne40c174b2014-10-20 01:02:48 +020049#endif
50
51#ifdef HAVE_LINUX_PTRACE_H
Denys Vlasenko84703742012-02-25 02:38:52 +010052# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000053# ifdef HAVE_STRUCT_IA64_FPREG
54# define ia64_fpreg XXX_ia64_fpreg
55# endif
56# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
57# define pt_all_user_regs XXX_pt_all_user_regs
58# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030059# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
60# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
61# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010062# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030063# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000064# undef ia64_fpreg
65# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000066#endif
67
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000068int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000069string_to_uint(const char *str)
70{
71 char *error;
72 long value;
73
74 if (!*str)
75 return -1;
76 errno = 0;
77 value = strtol(str, &error, 10);
78 if (errno || *error || value < 0 || (long)(int)value != value)
79 return -1;
80 return (int)value;
81}
82
83int
Dmitry V. Levin447db452014-05-29 17:59:01 +000084tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085{
86 return a->tv_sec || a->tv_usec;
87}
88
89int
Dmitry V. Levin447db452014-05-29 17:59:01 +000090tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000091{
92 if (a->tv_sec < b->tv_sec
93 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
94 return -1;
95 if (a->tv_sec > b->tv_sec
96 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
97 return 1;
98 return 0;
99}
100
101double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000102tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103{
104 return tv->tv_sec + tv->tv_usec/1000000.0;
105}
106
107void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000108tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109{
110 tv->tv_sec = a->tv_sec + b->tv_sec;
111 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000112 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113 tv->tv_sec++;
114 tv->tv_usec -= 1000000;
115 }
116}
117
118void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000119tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120{
121 tv->tv_sec = a->tv_sec - b->tv_sec;
122 tv->tv_usec = a->tv_usec - b->tv_usec;
123 if (((long) tv->tv_usec) < 0) {
124 tv->tv_sec--;
125 tv->tv_usec += 1000000;
126 }
127}
128
129void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000130tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131{
132 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
133 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
134 tv->tv_usec %= 1000000;
135}
136
137void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000138tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139{
140 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000141 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142 tv->tv_usec %= 1000000;
143}
144
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000145const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000146xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147{
148 for (; xlat->str != NULL; xlat++)
149 if (xlat->val == val)
150 return xlat->str;
151 return NULL;
152}
153
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000154static int
155xlat_bsearch_compare(const void *a, const void *b)
156{
157 const unsigned int val1 = (const unsigned long) a;
158 const unsigned int val2 = ((const struct xlat *) b)->val;
159 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
160}
161
162const char *
163xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
164{
165 const struct xlat *e =
166 bsearch((const void*) (const unsigned long) val,
167 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
168
169 return e ? e->str : NULL;
170}
171
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200172#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200173char *
174stpcpy(char *dst, const char *src)
175{
176 while ((*dst = *src++) != '\0')
177 dst++;
178 return dst;
179}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200180#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200181
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100182/* Find a next bit which is set.
183 * Starts testing at cur_bit.
184 * Returns -1 if no more bits are set.
185 *
186 * We never touch bytes we don't need to.
187 * On big-endian, array is assumed to consist of
188 * current_wordsize wide words: for example, is current_wordsize is 4,
189 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
190 * On little-endian machines, word size is immaterial.
191 */
192int
193next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
194{
195 const unsigned endian = 1;
196 int little_endian = *(char*)&endian;
197
198 const uint8_t *array = bit_array;
199 unsigned pos = cur_bit / 8;
200 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
201
202 for (;;) {
203 uint8_t bitmask;
204 uint8_t cur_byte;
205
206 if (cur_bit >= size_bits)
207 return -1;
208 cur_byte = array[pos ^ pos_xor_mask];
209 if (cur_byte == 0) {
210 cur_bit = (cur_bit + 8) & (-8);
211 pos++;
212 continue;
213 }
214 bitmask = 1 << (cur_bit & 7);
215 for (;;) {
216 if (cur_byte & bitmask)
217 return cur_bit;
218 cur_bit++;
219 if (cur_bit >= size_bits)
220 return -1;
221 bitmask <<= 1;
222 /* This check *can't be* optimized out: */
223 if (bitmask == 0)
224 break;
225 }
226 pos++;
227 }
228}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229/*
230 * Print entry in struct xlat table, if there.
231 */
232void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000233printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000235 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236
237 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200238 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000239 else
240 tprintf("%#x /* %s */", val, dflt);
241}
242
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100243/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100244 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100245 * argument.
246 */
247int
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000248printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100249{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000250#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
251# if SUPPORTED_PERSONALITIES > 1
252 if (current_wordsize > 4) {
253# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100254 tprintf(format, tcp->u_arg[arg_no]);
255 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000256# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100257 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000258# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000259 /* Align arg_no to the next even number. */
260 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000261# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100262 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
263 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100264 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000265# endif /* SUPPORTED_PERSONALITIES */
266#elif SIZEOF_LONG > 4
267# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
268#elif defined LINUX_MIPSN32
269 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100270 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000271#elif defined X32
272 if (current_personality == 0) {
273 tprintf(format, tcp->ext_arg[arg_no]);
274 arg_no++;
275 } else {
276 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
277 arg_no += 2;
278 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100279#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000280# if defined __ARM_EABI__ || \
281 defined LINUX_MIPSO32 || \
282 defined POWERPC || \
283 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000284 /* Align arg_no to the next even number. */
285 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000286# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100287 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
288 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100289#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000290
Chris Metcalf879dddd2013-03-01 10:41:02 +0100291 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100292}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100293
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294/*
295 * Interpret `xlat' as an array of flags
296 * print the entries whose bits are on in `flags'
297 * return # of flags printed.
298 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200299void
Denys Vlasenko12014262011-05-30 14:00:14 +0200300addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200302 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000303 if (xlat->val && (flags & xlat->val) == xlat->val) {
304 tprintf("|%s", xlat->str);
305 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000306 }
307 }
308 if (flags) {
309 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311}
312
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000313/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200314 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000315 * Print to static string the entries whose bits are on in `flags'
316 * Return static string.
317 */
318const char *
319sprintflags(const char *prefix, const struct xlat *xlat, int flags)
320{
321 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200322 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000323 int found = 0;
324
Denys Vlasenko52845572011-08-31 12:07:38 +0200325 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000326
327 for (; xlat->str; xlat++) {
328 if ((flags & xlat->val) == xlat->val) {
329 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200330 *outptr++ = '|';
331 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000332 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100333 flags &= ~xlat->val;
334 if (!flags)
335 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000336 }
337 }
338 if (flags) {
339 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200340 *outptr++ = '|';
341 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000342 }
343
344 return outstr;
345}
346
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000347int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000348printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000349{
350 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000351 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352
353 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200354 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000355 return 1;
356 }
357
358 sep = "";
359 for (n = 0; xlat->str; xlat++) {
360 if (xlat->val && (flags & xlat->val) == xlat->val) {
361 tprintf("%s%s", sep, xlat->str);
362 flags &= ~xlat->val;
363 sep = "|";
364 n++;
365 }
366 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000367
368 if (n) {
369 if (flags) {
370 tprintf("%s%#x", sep, flags);
371 n++;
372 }
373 } else {
374 if (flags) {
375 tprintf("%#x", flags);
376 if (dflt)
377 tprintf(" /* %s */", dflt);
378 } else {
379 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200380 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000381 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000383
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384 return n;
385}
386
387void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000388printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389{
Roland McGratheb285352003-01-14 09:59:00 +0000390 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391
392 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200393 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 return;
395 }
396 if (umove(tcp, addr, &num) < 0) {
397 tprintf("%#lx", addr);
398 return;
399 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200400 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000401 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200402 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403}
404
Roland McGrath6bc12202003-11-13 22:32:27 +0000405void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000406printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000407{
408 int num;
409
410 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200411 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000412 return;
413 }
414 if (umove(tcp, addr, &num) < 0) {
415 tprintf("%#lx", addr);
416 return;
417 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200418 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000419 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200420 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000421}
422
423void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300424printfd(struct tcb *tcp, int fd)
425{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100426 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000427 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
428 static const char socket_prefix[] = "socket:[";
429 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
430 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000431
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000432 if (show_fd_path > 1 &&
433 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
434 path[(path_len = strlen(path)) - 1] == ']') {
435 unsigned long inodenr;
436 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
437 tprintf("%d<", fd);
438 if (!print_sockaddr_by_inode(inodenr))
439 tprints(path);
440 tprints(">");
441 } else {
442 tprintf("%d<%s>", fd, path);
443 }
444 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000445 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300446}
447
448void
Denys Vlasenko12014262011-05-30 14:00:14 +0200449printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000450{
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000451 tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000452}
453
Dmitry V. Levina501f142008-11-10 23:19:13 +0000454/*
455 * Quote string `instr' of length `size'
456 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200457 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000458 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100459 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200460 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100461 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000462 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400463int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200464string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000465{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000466 const unsigned char *ustr = (const unsigned char *) instr;
467 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200468 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000469
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200470 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200471 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200472 size--;
473 eol = '\0';
474 }
475
476 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000477 if (xflag > 1)
478 usehex = 1;
479 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000480 /* Check for presence of symbol which require
481 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000482 for (i = 0; i < size; ++i) {
483 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000484 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200485 if (c == eol)
486 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100487
488 /* Force hex unless c is printable or whitespace */
489 if (c > 0x7e) {
490 usehex = 1;
491 break;
492 }
493 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
494 * They happen to have ASCII codes 9,10,11,12,13.
495 */
496 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000497 usehex = 1;
498 break;
499 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000500 }
501 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000502
503 *s++ = '\"';
504
505 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000506 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000507 for (i = 0; i < size; ++i) {
508 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000509 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200510 if (c == eol)
511 goto asciz_ended;
512 *s++ = '\\';
513 *s++ = 'x';
514 *s++ = "0123456789abcdef"[c >> 4];
515 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000516 }
517 } else {
518 for (i = 0; i < size; ++i) {
519 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000520 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200521 if (c == eol)
522 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000523 switch (c) {
524 case '\"': case '\\':
525 *s++ = '\\';
526 *s++ = c;
527 break;
528 case '\f':
529 *s++ = '\\';
530 *s++ = 'f';
531 break;
532 case '\n':
533 *s++ = '\\';
534 *s++ = 'n';
535 break;
536 case '\r':
537 *s++ = '\\';
538 *s++ = 'r';
539 break;
540 case '\t':
541 *s++ = '\\';
542 *s++ = 't';
543 break;
544 case '\v':
545 *s++ = '\\';
546 *s++ = 'v';
547 break;
548 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100549 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200551 else {
552 /* Print \octal */
553 *s++ = '\\';
554 if (i + 1 < size
555 && ustr[i + 1] >= '0'
556 && ustr[i + 1] <= '9'
557 ) {
558 /* Print \ooo */
559 *s++ = '0' + (c >> 6);
560 *s++ = '0' + ((c >> 3) & 0x7);
561 } else {
562 /* Print \[[o]o]o */
563 if ((c >> 3) != 0) {
564 if ((c >> 6) != 0)
565 *s++ = '0' + (c >> 6);
566 *s++ = '0' + ((c >> 3) & 0x7);
567 }
568 }
569 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000570 }
571 break;
572 }
573 }
574 }
575
576 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000577 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000578
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200579 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200580 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200581 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
582 * but next char is NUL.
583 */
584 return 0;
585 }
586
587 return 1;
588
589 asciz_ended:
590 *s++ = '\"';
591 *s = '\0';
592 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
593 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594}
595
Dmitry V. Levina501f142008-11-10 23:19:13 +0000596/*
597 * Print path string specified by address `addr' and length `n'.
598 * If path length exceeds `n', append `...' to the output.
599 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000601printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100603 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100604 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100605
Dmitry V. Levina501f142008-11-10 23:19:13 +0000606 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200607 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000608 return;
609 }
610
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100611 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000612 if (n > sizeof path - 1)
613 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000614
615 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100616 nul_seen = umovestr(tcp, addr, n + 1, path);
617 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618 tprintf("%#lx", addr);
619 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100620 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000621
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100622 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100623 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100624 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100625 string_quote(path, outstr, -1, n);
626 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100627 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100628 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000629 }
630}
631
632void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000633printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000634{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100635 /* Size must correspond to char path[] size in printpathn */
636 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000637}
638
Dmitry V. Levina501f142008-11-10 23:19:13 +0000639/*
640 * Print string specified by address `addr' and length `len'.
641 * If `len' < 0, treat the string as a NUL-terminated string.
642 * If string length exceeds `max_strlen', append `...' to the output.
643 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000644void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200645printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000646{
647 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000649 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100650 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651
652 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200653 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654 return;
655 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000656 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200657 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000658 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
659
660 if (outstr_size / 4 != max_strlen)
661 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000662 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200663 if (!str)
664 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000665 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200666 if (!outstr)
667 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000668 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000669
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200670 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000671 /*
672 * Treat as a NUL-terminated string: fetch one byte more
673 * because string_quote() quotes one byte less.
674 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000675 size = max_strlen + 1;
676 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000677 tprintf("%#lx", addr);
678 return;
679 }
680 }
681 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200682 size = max_strlen;
683 if (size > (unsigned long)len)
684 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000685 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 tprintf("%#lx", addr);
687 return;
688 }
689 }
690
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100691 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
692 * or we were requested to print more than -s NUM chars)...
693 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100694 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000695 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000696
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100697 tprints(outstr);
698 if (ellipsis)
699 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700}
701
John Hughes1d08dcf2001-07-10 13:48:44 +0000702#if HAVE_SYS_UIO_H
703void
Denys Vlasenko12014262011-05-30 14:00:14 +0200704dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000705{
Denys Vlasenko84703742012-02-25 02:38:52 +0100706#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000707 union {
708 struct { u_int32_t base; u_int32_t len; } *iov32;
709 struct { u_int64_t base; u_int64_t len; } *iov64;
710 } iovu;
711#define iov iovu.iov64
712#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100713 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000714#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100715 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000716#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100717 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000718#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000719 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000720#define sizeof_iov sizeof(*iov)
721#define iov_iov_base(i) iov[i].iov_base
722#define iov_iov_len(i) iov[i].iov_len
723#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000724 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200725 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000726
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200727 size = sizeof_iov * len;
728 /* Assuming no sane program has millions of iovs */
729 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000730 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200731 fprintf(stderr, "Out of memory\n");
732 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000733 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000734 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000735 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000736 /* include the buffer number to make it easy to
737 * match up the trace with the source */
738 tprintf(" * %lu bytes in buffer %d\n",
739 (unsigned long)iov_iov_len(i), i);
740 dumpstr(tcp, (long) iov_iov_base(i),
741 iov_iov_len(i));
742 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000743 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200744 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000745#undef sizeof_iov
746#undef iov_iov_base
747#undef iov_iov_len
748#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000749}
750#endif
751
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752void
Denys Vlasenko12014262011-05-30 14:00:14 +0200753dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000754{
755 static int strsize = -1;
756 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757
Denys Vlasenko76325802013-02-22 14:47:39 +0100758 char outbuf[
759 (
760 (sizeof(
761 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
762 "1234567890123456") + /*in case I'm off by few:*/ 4)
763 /*align to 8 to make memset easier:*/ + 7) & -8
764 ];
765 const unsigned char *src;
766 int i;
767
768 memset(outbuf, ' ', sizeof(outbuf));
769
770 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200771 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100772 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200773 if (!str) {
774 strsize = -1;
775 fprintf(stderr, "Out of memory\n");
776 return;
777 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100778 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 }
780
781 if (umoven(tcp, addr, len, (char *) str) < 0)
782 return;
783
Denys Vlasenko76325802013-02-22 14:47:39 +0100784 /* Space-pad to 16 bytes */
785 i = len;
786 while (i & 0xf)
787 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200788
Denys Vlasenko76325802013-02-22 14:47:39 +0100789 i = 0;
790 src = str;
791 while (i < len) {
792 char *dst = outbuf;
793 /* Hex dump */
794 do {
795 if (i < len) {
796 *dst++ = "0123456789abcdef"[*src >> 4];
797 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000798 }
799 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100800 *dst++ = ' ';
801 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100803 dst++; /* space is there by memset */
804 i++;
805 if ((i & 7) == 0)
806 dst++; /* space is there by memset */
807 src++;
808 } while (i & 0xf);
809 /* ASCII dump */
810 i -= 16;
811 src -= 16;
812 do {
813 if (*src >= ' ' && *src < 0x7f)
814 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100816 *dst++ = '.';
817 src++;
818 } while (++i & 0xf);
819 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100820 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 }
822}
823
Mike Frysinger612659e2012-02-14 14:38:28 +0100824#ifdef HAVE_PROCESS_VM_READV
825/* C library supports this, but the kernel might not. */
826static bool process_vm_readv_not_supported = 0;
827#else
828
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100829/* Need to do this since process_vm_readv() is not yet available in libc.
830 * When libc is be updated, only "static bool process_vm_readv_not_supported"
831 * line should remain.
832 */
833#if !defined(__NR_process_vm_readv)
834# if defined(I386)
835# define __NR_process_vm_readv 347
836# elif defined(X86_64)
837# define __NR_process_vm_readv 310
838# elif defined(POWERPC)
839# define __NR_process_vm_readv 351
840# endif
841#endif
842
843#if defined(__NR_process_vm_readv)
844static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400845/* Have to avoid duplicating with the C library headers. */
846static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100847 const struct iovec *lvec,
848 unsigned long liovcnt,
849 const struct iovec *rvec,
850 unsigned long riovcnt,
851 unsigned long flags)
852{
853 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
854}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400855#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100856#else
857static bool process_vm_readv_not_supported = 1;
858# define process_vm_readv(...) (errno = ENOSYS, -1)
859#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100860
861#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100862
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863#define PAGMASK (~(PAGSIZ - 1))
864/*
865 * move `len' bytes of data from process `pid'
866 * at address `addr' to our space at `laddr'
867 */
868int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000869umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700871 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000872 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873 union {
874 long val;
875 char x[sizeof(long)];
876 } u;
877
Denys Vlasenko2544f982013-02-19 17:39:56 +0100878#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100879 if (current_wordsize < sizeof(addr))
880 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100881#endif
882
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100883 if (!process_vm_readv_not_supported) {
884 struct iovec local[1], remote[1];
885 int r;
886
887 local[0].iov_base = laddr;
888 remote[0].iov_base = (void*)addr;
889 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000890 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100891 if (r == len)
892 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000893 if (r >= 0) {
894 error_msg("umoven: short read (%d < %d) @0x%lx",
895 r, len, addr);
896 return -1;
897 }
898 switch (errno) {
899 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100900 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000901 break;
902 case ESRCH:
903 /* the process is gone */
904 return -1;
905 case EFAULT: case EIO: case EPERM:
906 /* address space is inaccessible */
907 return -1;
908 default:
909 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100910 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000911 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100912 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100913 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100914
Dmitry V. Levin97005922013-02-26 21:16:22 +0000915 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 if (addr & (sizeof(long) - 1)) {
917 /* addr not a multiple of sizeof(long) */
918 n = addr - (addr & -sizeof(long)); /* residue */
919 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700920 errno = 0;
921 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000922 switch (errno) {
923 case 0:
924 break;
925 case ESRCH: case EINVAL:
926 /* these could be seen if the process is gone */
927 return -1;
928 case EFAULT: case EIO: case EPERM:
929 /* address space is inaccessible */
930 return -1;
931 default:
932 /* all the rest is strange and should be reported */
933 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
934 pid, addr);
935 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700936 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100937 m = MIN(sizeof(long) - n, len);
938 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100939 addr += sizeof(long);
940 laddr += m;
941 nread += m;
942 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943 }
944 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700945 errno = 0;
946 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000947 switch (errno) {
948 case 0:
949 break;
950 case ESRCH: case EINVAL:
951 /* these could be seen if the process is gone */
952 return -1;
953 case EFAULT: case EIO: case EPERM:
954 /* address space is inaccessible */
955 if (nread) {
956 perror_msg("umoven: short read (%d < %d) @0x%lx",
957 nread, nread + len, addr - nread);
958 }
959 return -1;
960 default:
961 /* all the rest is strange and should be reported */
962 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
963 pid, addr);
964 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700965 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100966 m = MIN(sizeof(long), len);
967 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100968 addr += sizeof(long);
969 laddr += m;
970 nread += m;
971 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 return 0;
975}
976
977/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100978 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100980 *
981 * Returns < 0 on error, > 0 if NUL was seen,
982 * (TODO if useful: return count of bytes including NUL),
983 * else 0 if len bytes were read but no NUL byte seen.
984 *
985 * Note: there is no guarantee we won't overwrite some bytes
986 * in laddr[] _after_ terminating NUL (but, of course,
987 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 */
989int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000990umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991{
Denys Vlasenko16940922013-03-01 18:52:59 +0100992#if SIZEOF_LONG == 4
993 const unsigned long x01010101 = 0x01010101ul;
994 const unsigned long x80808080 = 0x80808080ul;
995#elif SIZEOF_LONG == 8
996 const unsigned long x01010101 = 0x0101010101010101ul;
997 const unsigned long x80808080 = 0x8080808080808080ul;
998#else
999# error SIZEOF_LONG > 8
1000#endif
1001
Roland McGratheb9e2e82009-06-02 16:49:22 -07001002 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +01001003 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001005 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 char x[sizeof(long)];
1007 } u;
1008
Denys Vlasenko2544f982013-02-19 17:39:56 +01001009#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001010 if (current_wordsize < sizeof(addr))
1011 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001012#endif
1013
Dmitry V. Levin97005922013-02-26 21:16:22 +00001014 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001015 if (!process_vm_readv_not_supported) {
1016 struct iovec local[1], remote[1];
1017
1018 local[0].iov_base = laddr;
1019 remote[0].iov_base = (void*)addr;
1020
1021 while (len > 0) {
1022 int end_in_page;
1023 int r;
1024 int chunk_len;
1025
1026 /* Don't read kilobytes: most strings are short */
1027 chunk_len = len;
1028 if (chunk_len > 256)
1029 chunk_len = 256;
1030 /* Don't cross pages. I guess otherwise we can get EFAULT
1031 * and fail to notice that terminating NUL lies
1032 * in the existing (first) page.
1033 * (I hope there aren't arches with pages < 4K)
1034 */
1035 end_in_page = ((addr + chunk_len) & 4095);
1036 r = chunk_len - end_in_page;
1037 if (r > 0) /* if chunk_len > end_in_page */
1038 chunk_len = r; /* chunk_len -= end_in_page */
1039
1040 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001041 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1042 if (r > 0) {
1043 if (memchr(local[0].iov_base, '\0', r))
1044 return 1;
1045 local[0].iov_base += r;
1046 remote[0].iov_base += r;
1047 len -= r;
1048 nread += r;
1049 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001050 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001051 switch (errno) {
1052 case ENOSYS:
1053 process_vm_readv_not_supported = 1;
1054 goto vm_readv_didnt_work;
1055 case ESRCH:
1056 /* the process is gone */
1057 return -1;
1058 case EFAULT: case EIO: case EPERM:
1059 /* address space is inaccessible */
1060 if (nread) {
1061 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1062 nread, nread + len, addr);
1063 }
1064 return -1;
1065 default:
1066 /* all the rest is strange and should be reported */
1067 perror_msg("process_vm_readv");
1068 return -1;
1069 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001070 }
1071 return 0;
1072 }
1073 vm_readv_didnt_work:
1074
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 if (addr & (sizeof(long) - 1)) {
1076 /* addr not a multiple of sizeof(long) */
1077 n = addr - (addr & -sizeof(long)); /* residue */
1078 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001079 errno = 0;
1080 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001081 switch (errno) {
1082 case 0:
1083 break;
1084 case ESRCH: case EINVAL:
1085 /* these could be seen if the process is gone */
1086 return -1;
1087 case EFAULT: case EIO: case EPERM:
1088 /* address space is inaccessible */
1089 return -1;
1090 default:
1091 /* all the rest is strange and should be reported */
1092 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1093 pid, addr);
1094 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001095 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001096 m = MIN(sizeof(long) - n, len);
1097 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 while (n & (sizeof(long) - 1))
1099 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001100 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001101 addr += sizeof(long);
1102 laddr += m;
1103 nread += m;
1104 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001106
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001108 errno = 0;
1109 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001110 switch (errno) {
1111 case 0:
1112 break;
1113 case ESRCH: case EINVAL:
1114 /* these could be seen if the process is gone */
1115 return -1;
1116 case EFAULT: case EIO: case EPERM:
1117 /* address space is inaccessible */
1118 if (nread) {
1119 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1120 nread, nread + len, addr - nread);
1121 }
1122 return -1;
1123 default:
1124 /* all the rest is strange and should be reported */
1125 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1126 pid, addr);
1127 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001128 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001129 m = MIN(sizeof(long), len);
1130 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001131 /* "If a NUL char exists in this word" */
1132 if ((u.val - x01010101) & ~u.val & x80808080)
1133 return 1;
1134 addr += sizeof(long);
1135 laddr += m;
1136 nread += m;
1137 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001139 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140}
1141
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001143upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144{
1145 long val;
1146
Roland McGratheb9e2e82009-06-02 16:49:22 -07001147 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001148 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001149 if (val == -1 && errno) {
1150 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001151 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001152 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001154 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 *res = val;
1156 return 0;
1157}
1158
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001159/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1160 * and PTRACE_O_TRACE[V]FORK for tracing children.
1161 * If you are adding a new arch which is only supported by newer kernels,
1162 * you most likely don't need to add any code below
1163 * beside a dummy "return 0" block in change_syscall().
1164 */
1165
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001166/*
1167 * These #if's are huge, please indent them correctly.
1168 * It's easy to get confused otherwise.
1169 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001171#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001172
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001173#ifndef CLONE_PTRACE
1174# define CLONE_PTRACE 0x00002000
1175#endif
1176#ifndef CLONE_VFORK
1177# define CLONE_VFORK 0x00004000
1178#endif
1179#ifndef CLONE_VM
1180# define CLONE_VM 0x00000100
1181#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001183#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001184
1185typedef unsigned long *arg_setup_state;
1186
1187static int
1188arg_setup(struct tcb *tcp, arg_setup_state *state)
1189{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001190 unsigned long cfm, sof, sol;
1191 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001192
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001193 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001194 /* Satisfy a false GCC warning. */
1195 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001196 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001197 }
Roland McGrath08267b82004-02-20 22:56:43 +00001198
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001199 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001200 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001201 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202 return -1;
1203
1204 sof = (cfm >> 0) & 0x7f;
1205 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001206 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001207
Jan Kratochvil1f942712008-08-06 21:38:52 +00001208 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001209 return 0;
1210}
1211
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001212# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001213
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001215get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001216{
Roland McGrath08267b82004-02-20 22:56:43 +00001217 int ret;
1218
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001219 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001220 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001221 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001222 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001223 (unsigned long) ia64_rse_skip_regs(*state, 0),
1224 sizeof(long), (void *) valp);
1225 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226}
1227
1228static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001229get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001230{
Roland McGrath08267b82004-02-20 22:56:43 +00001231 int ret;
1232
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001233 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001234 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001235 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001236 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001237 (unsigned long) ia64_rse_skip_regs(*state, 1),
1238 sizeof(long), (void *) valp);
1239 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001240}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001241
1242static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001243set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001244{
Roland McGrath08267b82004-02-20 22:56:43 +00001245 int req = PTRACE_POKEDATA;
1246 void *ap;
1247
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001248 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001249 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1250 req = PTRACE_POKEUSER;
1251 } else
1252 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001253 errno = 0;
1254 ptrace(req, tcp->pid, ap, val);
1255 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001256}
1257
1258static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001259set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001260{
Roland McGrath08267b82004-02-20 22:56:43 +00001261 int req = PTRACE_POKEDATA;
1262 void *ap;
1263
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001264 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001265 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1266 req = PTRACE_POKEUSER;
1267 } else
1268 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001269 errno = 0;
1270 ptrace(req, tcp->pid, ap, val);
1271 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272}
1273
Roland McGrathb659f872008-07-18 01:19:36 +00001274/* ia64 does not return the input arguments from functions (and syscalls)
1275 according to ia64 RSE (Register Stack Engine) behavior. */
1276
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001277# define restore_arg0(tcp, state, val) ((void) (state), 0)
1278# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001279
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001280#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001282# if defined(SPARC64)
1283# undef PTRACE_GETREGS
1284# define PTRACE_GETREGS PTRACE_GETREGS64
1285# undef PTRACE_SETREGS
1286# define PTRACE_SETREGS PTRACE_SETREGS64
1287# endif
1288
Mike Frysinger8566c502009-10-12 11:05:14 -04001289typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001291# define arg_setup(tcp, state) \
1292 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1293# define arg_finish_change(tcp, state) \
1294 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001296# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1297# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1298# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1299# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1300# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001302#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001304# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001305/* Note: this is only true for the `clone' system call, which handles
1306 arguments specially. We could as well say that its first two arguments
1307 are swapped relative to other architectures, but that would just be
1308 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001309# define arg0_offset PT_GPR3
1310# define arg1_offset PT_ORIGGPR2
1311# define restore_arg0(tcp, state, val) ((void) (state), 0)
1312# define restore_arg1(tcp, state, val) ((void) (state), 0)
1313# define arg0_index 1
1314# define arg1_index 0
1315# elif defined(ALPHA) || defined(MIPS)
1316# define arg0_offset REG_A0
1317# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001318# elif defined(POWERPC)
1319# define arg0_offset (sizeof(unsigned long)*PT_R3)
1320# define arg1_offset (sizeof(unsigned long)*PT_R4)
1321# define restore_arg0(tcp, state, val) ((void) (state), 0)
1322# elif defined(HPPA)
1323# define arg0_offset PT_GR26
1324# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001325# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001326# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1327# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1328# elif defined(SH)
1329# define arg0_offset (4*(REG_REG0+4))
1330# define arg1_offset (4*(REG_REG0+5))
1331# elif defined(SH64)
1332 /* ABI defines arg0 & 1 in r2 & r3 */
1333# define arg0_offset (REG_OFFSET+16)
1334# define arg1_offset (REG_OFFSET+24)
1335# define restore_arg0(tcp, state, val) 0
1336# elif defined CRISV10 || defined CRISV32
1337# define arg0_offset (4*PT_R11)
1338# define arg1_offset (4*PT_ORIG_R10)
1339# define restore_arg0(tcp, state, val) 0
1340# define restore_arg1(tcp, state, val) 0
1341# define arg0_index 1
1342# define arg1_index 0
1343# else
1344# define arg0_offset 0
1345# define arg1_offset 4
1346# if defined ARM
1347# define restore_arg0(tcp, state, val) 0
1348# endif
1349# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001350
1351typedef int arg_setup_state;
1352
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001353# define arg_setup(tcp, state) (0)
1354# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001355# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1356# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357
1358static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001359set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001361 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001362}
1363
1364static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001365set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001367 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001368}
1369
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001370#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001372#ifndef restore_arg0
1373# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1374#endif
1375#ifndef restore_arg1
1376# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1377#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001378
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001379#ifndef arg0_index
1380# define arg0_index 0
1381# define arg1_index 1
1382#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001383
James Hogan05eb9052012-11-29 17:37:37 +00001384static int
1385change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1386{
1387#if defined(I386)
1388 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1389 return -1;
1390 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001391#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001392 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1393 return -1;
1394 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001395#elif defined(X32)
1396 /* setbpt/clearbpt never used: */
1397 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001398#elif defined(POWERPC)
1399 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1400 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1401 return -1;
1402 return 0;
1403#elif defined(S390) || defined(S390X)
1404 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1405 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1406 return -1;
1407 return 0;
1408#elif defined(M68K)
1409 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1410 return -1;
1411 return 0;
1412#elif defined(SPARC) || defined(SPARC64)
1413 state->u_regs[U_REG_G1] = new;
1414 return 0;
1415#elif defined(MIPS)
1416 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1417 return -1;
1418 return 0;
1419#elif defined(ALPHA)
1420 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1421 return -1;
1422 return 0;
1423#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001424 /* setbpt/clearbpt never used: */
1425 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001426#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001427 /* setbpt/clearbpt never used: */
1428 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001429#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001430 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001431 switch (new) {
1432 case 2:
1433 break; /* x86 SYS_fork */
1434 case SYS_clone:
1435 new = 120;
1436 break;
1437 default:
1438 fprintf(stderr, "%s: unexpected syscall %d\n",
1439 __FUNCTION__, new);
1440 return -1;
1441 }
1442 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1443 return -1;
1444 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1445 return -1;
1446 return 0;
1447#elif defined(HPPA)
1448 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1449 return -1;
1450 return 0;
1451#elif defined(SH)
1452 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1453 return -1;
1454 return 0;
1455#elif defined(SH64)
1456 /* Top half of reg encodes the no. of args n as 0x1n.
1457 Assume 0 args as kernel never actually checks... */
1458 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1459 0x100000 | new) < 0)
1460 return -1;
1461 return 0;
1462#elif defined(CRISV10) || defined(CRISV32)
1463 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1464 return -1;
1465 return 0;
1466#elif defined(ARM)
1467 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1468# ifndef PTRACE_SET_SYSCALL
1469# define PTRACE_SET_SYSCALL 23
1470# endif
1471 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1472 return -1;
1473 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001474#elif defined(AARCH64)
1475 /* setbpt/clearbpt never used: */
1476 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001477#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001478 /* setbpt/clearbpt never used: */
1479 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001480#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001481 /* setbpt/clearbpt never used: */
1482 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001483#elif defined(OR1K)
1484 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001485#elif defined(METAG)
1486 /* setbpt/clearbpt never used: */
1487 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001488#elif defined(XTENSA)
1489 /* setbpt/clearbpt never used: */
1490 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301491#elif defined(ARC)
1492 /* setbpt/clearbpt never used: */
1493 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001494#else
1495#warning Do not know how to handle change_syscall for this architecture
1496#endif /* architecture */
1497 return -1;
1498}
1499
Roland McGrathd81f1d92003-01-09 06:53:34 +00001500int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001501setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001502{
Roland McGrath3291ef22008-05-20 00:34:34 +00001503 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001504 arg_setup_state state;
1505
1506 if (tcp->flags & TCB_BPTSET) {
1507 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1508 return -1;
1509 }
1510
Roland McGrath3291ef22008-05-20 00:34:34 +00001511 /*
1512 * It's a silly kludge to initialize this with a search at runtime.
1513 * But it's better than maintaining another magic thing in the
1514 * godforsaken tables.
1515 */
1516 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001517 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001518 for (i = 0; i < nsyscalls; ++i)
1519 if (sysent[i].sys_func == sys_clone) {
1520 clone_scno[current_personality] = i;
1521 break;
1522 }
1523 }
1524
Dmitry V. Levin65563152014-05-12 13:43:10 +00001525 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001526 if (arg_setup(tcp, &state) < 0
1527 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1528 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001529 || change_syscall(tcp, &state,
1530 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001531 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1532 || set_arg1(tcp, &state, 0) < 0
1533 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001534 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001535 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1536 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001537 tcp->flags |= TCB_BPTSET;
1538 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001539 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001540
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001541 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001542 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001543 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001544 vfork semantics into plain fork - each application must not
1545 depend on the vfork specifics according to POSIX. We would
1546 hang waiting for the parent resume otherwise. We need to
1547 clear also CLONE_VM but only in the CLONE_VFORK case as
1548 otherwise we would break pthread_create. */
1549
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001550 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1551 if (new_arg0 & CLONE_VFORK)
1552 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1553 if (arg_setup(tcp, &state) < 0
1554 || set_arg0(tcp, &state, new_arg0) < 0
1555 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001556 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001557 tcp->inst[0] = tcp->u_arg[arg0_index];
1558 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001559 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001560 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001561 }
1562
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001563 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1564 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001565 return -1;
1566}
1567
1568int
Denys Vlasenko12014262011-05-30 14:00:14 +02001569clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001570{
1571 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001572 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001573 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001574 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1575 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1576 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001577 if (errno != ESRCH)
1578 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001579 tcp->flags &= ~TCB_BPTSET;
1580 return 0;
1581}