blob: 71e921d02cfda2bb4ad4bb307e153aaa5084cc4b [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
36#include <sys/param.h>
37#include <fcntl.h>
Masatake YAMATOf5480672014-11-22 19:03:33 +090038#if HAVE_SYS_XATTR_H
39# include <sys/xattr.h>
40#endif
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000041#include <sys/uio.h>
Wichert Akkerman36915a11999-07-13 15:45:02 +000042
Denys Vlasenko84703742012-02-25 02:38:52 +010043#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000044# include <asm/ptrace_offsets.h>
45# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000046#endif
47
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010049# include <sys/reg.h>
Maarten ter Huurne40c174b2014-10-20 01:02:48 +020050#endif
51
52#ifdef HAVE_LINUX_PTRACE_H
Denys Vlasenko84703742012-02-25 02:38:52 +010053# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000054# ifdef HAVE_STRUCT_IA64_FPREG
55# define ia64_fpreg XXX_ia64_fpreg
56# endif
57# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
58# define pt_all_user_regs XXX_pt_all_user_regs
59# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030060# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
61# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
62# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010063# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030064# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000065# undef ia64_fpreg
66# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000070string_to_uint(const char *str)
71{
72 char *error;
73 long value;
74
75 if (!*str)
76 return -1;
77 errno = 0;
78 value = strtol(str, &error, 10);
79 if (errno || *error || value < 0 || (long)(int)value != value)
80 return -1;
81 return (int)value;
82}
83
84int
Dmitry V. Levin447db452014-05-29 17:59:01 +000085tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086{
87 return a->tv_sec || a->tv_usec;
88}
89
90int
Dmitry V. Levin447db452014-05-29 17:59:01 +000091tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092{
93 if (a->tv_sec < b->tv_sec
94 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
95 return -1;
96 if (a->tv_sec > b->tv_sec
97 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
98 return 1;
99 return 0;
100}
101
102double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000103tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104{
105 return tv->tv_sec + tv->tv_usec/1000000.0;
106}
107
108void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000109tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110{
111 tv->tv_sec = a->tv_sec + b->tv_sec;
112 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000113 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114 tv->tv_sec++;
115 tv->tv_usec -= 1000000;
116 }
117}
118
119void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000120tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121{
122 tv->tv_sec = a->tv_sec - b->tv_sec;
123 tv->tv_usec = a->tv_usec - b->tv_usec;
124 if (((long) tv->tv_usec) < 0) {
125 tv->tv_sec--;
126 tv->tv_usec += 1000000;
127 }
128}
129
130void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000131tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132{
133 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
134 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
135 tv->tv_usec %= 1000000;
136}
137
138void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000139tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140{
141 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000142 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143 tv->tv_usec %= 1000000;
144}
145
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000146const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000147xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148{
149 for (; xlat->str != NULL; xlat++)
150 if (xlat->val == val)
151 return xlat->str;
152 return NULL;
153}
154
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000155static int
156xlat_bsearch_compare(const void *a, const void *b)
157{
158 const unsigned int val1 = (const unsigned long) a;
159 const unsigned int val2 = ((const struct xlat *) b)->val;
160 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
161}
162
163const char *
164xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
165{
166 const struct xlat *e =
167 bsearch((const void*) (const unsigned long) val,
168 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
169
170 return e ? e->str : NULL;
171}
172
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200173#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200174char *
175stpcpy(char *dst, const char *src)
176{
177 while ((*dst = *src++) != '\0')
178 dst++;
179 return dst;
180}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200181#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200182
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100183/* Find a next bit which is set.
184 * Starts testing at cur_bit.
185 * Returns -1 if no more bits are set.
186 *
187 * We never touch bytes we don't need to.
188 * On big-endian, array is assumed to consist of
189 * current_wordsize wide words: for example, is current_wordsize is 4,
190 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
191 * On little-endian machines, word size is immaterial.
192 */
193int
194next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
195{
196 const unsigned endian = 1;
197 int little_endian = *(char*)&endian;
198
199 const uint8_t *array = bit_array;
200 unsigned pos = cur_bit / 8;
201 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
202
203 for (;;) {
204 uint8_t bitmask;
205 uint8_t cur_byte;
206
207 if (cur_bit >= size_bits)
208 return -1;
209 cur_byte = array[pos ^ pos_xor_mask];
210 if (cur_byte == 0) {
211 cur_bit = (cur_bit + 8) & (-8);
212 pos++;
213 continue;
214 }
215 bitmask = 1 << (cur_bit & 7);
216 for (;;) {
217 if (cur_byte & bitmask)
218 return cur_bit;
219 cur_bit++;
220 if (cur_bit >= size_bits)
221 return -1;
222 bitmask <<= 1;
223 /* This check *can't be* optimized out: */
224 if (bitmask == 0)
225 break;
226 }
227 pos++;
228 }
229}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230/*
231 * Print entry in struct xlat table, if there.
232 */
233void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000234printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000236 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237
238 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200239 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 else
241 tprintf("%#x /* %s */", val, dflt);
242}
243
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100244/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100245 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100246 * argument.
247 */
248int
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000249printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100250{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000251#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
252# if SUPPORTED_PERSONALITIES > 1
253 if (current_wordsize > 4) {
254# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100255 tprintf(format, tcp->u_arg[arg_no]);
256 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000257# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100258 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000259# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000260 /* Align arg_no to the next even number. */
261 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000262# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100263 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
264 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100265 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000266# endif /* SUPPORTED_PERSONALITIES */
267#elif SIZEOF_LONG > 4
268# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
269#elif defined LINUX_MIPSN32
270 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100271 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000272#elif defined X32
273 if (current_personality == 0) {
274 tprintf(format, tcp->ext_arg[arg_no]);
275 arg_no++;
276 } else {
277 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
278 arg_no += 2;
279 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100280#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000281# if defined __ARM_EABI__ || \
282 defined LINUX_MIPSO32 || \
283 defined POWERPC || \
284 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000285 /* Align arg_no to the next even number. */
286 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000287# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100288 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
289 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100290#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000291
Chris Metcalf879dddd2013-03-01 10:41:02 +0100292 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100293}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100294
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295/*
296 * Interpret `xlat' as an array of flags
297 * print the entries whose bits are on in `flags'
298 * return # of flags printed.
299 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200300void
Denys Vlasenko12014262011-05-30 14:00:14 +0200301addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200303 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304 if (xlat->val && (flags & xlat->val) == xlat->val) {
305 tprintf("|%s", xlat->str);
306 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307 }
308 }
309 if (flags) {
310 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312}
313
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000314/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200315 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000316 * Print to static string the entries whose bits are on in `flags'
317 * Return static string.
318 */
319const char *
320sprintflags(const char *prefix, const struct xlat *xlat, int flags)
321{
322 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200323 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000324 int found = 0;
325
Denys Vlasenko52845572011-08-31 12:07:38 +0200326 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000327
328 for (; xlat->str; xlat++) {
329 if ((flags & xlat->val) == xlat->val) {
330 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200331 *outptr++ = '|';
332 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000333 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100334 flags &= ~xlat->val;
335 if (!flags)
336 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000337 }
338 }
339 if (flags) {
340 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200341 *outptr++ = '|';
342 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000343 }
344
345 return outstr;
346}
347
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000348int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000349printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350{
351 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000352 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353
354 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200355 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356 return 1;
357 }
358
359 sep = "";
360 for (n = 0; xlat->str; xlat++) {
361 if (xlat->val && (flags & xlat->val) == xlat->val) {
362 tprintf("%s%s", sep, xlat->str);
363 flags &= ~xlat->val;
364 sep = "|";
365 n++;
366 }
367 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000368
369 if (n) {
370 if (flags) {
371 tprintf("%s%#x", sep, flags);
372 n++;
373 }
374 } else {
375 if (flags) {
376 tprintf("%#x", flags);
377 if (dflt)
378 tprintf(" /* %s */", dflt);
379 } else {
380 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200381 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000382 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000384
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 return n;
386}
387
388void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000389printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390{
Roland McGratheb285352003-01-14 09:59:00 +0000391 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392
393 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200394 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000395 return;
396 }
397 if (umove(tcp, addr, &num) < 0) {
398 tprintf("%#lx", addr);
399 return;
400 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200401 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200403 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404}
405
Roland McGrath6bc12202003-11-13 22:32:27 +0000406void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000407printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000408{
409 int num;
410
411 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200412 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000413 return;
414 }
415 if (umove(tcp, addr, &num) < 0) {
416 tprintf("%#lx", addr);
417 return;
418 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200419 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000420 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200421 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000422}
423
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000424const char *
425sprinttime(time_t t)
426{
427 struct tm *tmp;
428 static char buf[sizeof("yyyy/mm/dd-hh:mm:ss")];
429
430 if (t == 0) {
431 strcpy(buf, "0");
432 return buf;
433 }
434 tmp = localtime(&t);
435 if (tmp)
436 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
437 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
438 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
439 else
440 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
441
442 return buf;
443}
444
Masatake YAMATOf5480672014-11-22 19:03:33 +0900445static char *
446getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
447{
448#if HAVE_SYS_XATTR_H
449 ssize_t r;
450 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
451
452 if (fd < 0)
453 return NULL;
454
455 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
456 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
457 if (r <= 0)
458 return NULL;
459 else {
460 /*
461 * This is a protection for the case when the kernel
462 * side does not append a null byte to the buffer.
463 */
464 buf[r] = '\0';
465 return buf;
466 }
467#else
468 return NULL;
469#endif
470}
471
Roland McGrath9814a942005-07-04 23:28:10 +0000472void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300473printfd(struct tcb *tcp, int fd)
474{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100475 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000476 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
477 static const char socket_prefix[] = "socket:[";
478 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
479 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000480
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000481 if (show_fd_path > 1 &&
482 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
483 path[(path_len = strlen(path)) - 1] == ']') {
484 unsigned long inodenr;
485 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
486 tprintf("%d<", fd);
Masatake YAMATOf5480672014-11-22 19:03:33 +0900487 if (!print_sockaddr_by_inode(inodenr)) {
488#define PROTO_NAME_LEN 32
489 char proto_buf[PROTO_NAME_LEN];
490 const char *proto =
491 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
492
493 if (proto)
494 tprintf("%s:[%lu]", proto, inodenr);
495 else
496 tprints(path);
497 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000498 tprints(">");
499 } else {
500 tprintf("%d<%s>", fd, path);
501 }
502 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000503 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300504}
505
506void
Denys Vlasenko12014262011-05-30 14:00:14 +0200507printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000508{
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000509 tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000510}
511
Dmitry V. Levina501f142008-11-10 23:19:13 +0000512/*
513 * Quote string `instr' of length `size'
514 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200515 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000516 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100517 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200518 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100519 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000520 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400521int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200522string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000524 const unsigned char *ustr = (const unsigned char *) instr;
525 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200526 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200528 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200529 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200530 size--;
531 eol = '\0';
532 }
533
534 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000535 if (xflag > 1)
536 usehex = 1;
537 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000538 /* Check for presence of symbol which require
539 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000540 for (i = 0; i < size; ++i) {
541 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000542 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200543 if (c == eol)
544 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100545
546 /* Force hex unless c is printable or whitespace */
547 if (c > 0x7e) {
548 usehex = 1;
549 break;
550 }
551 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
552 * They happen to have ASCII codes 9,10,11,12,13.
553 */
554 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000555 usehex = 1;
556 break;
557 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558 }
559 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000560
561 *s++ = '\"';
562
563 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000564 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 for (i = 0; i < size; ++i) {
566 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000567 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200568 if (c == eol)
569 goto asciz_ended;
570 *s++ = '\\';
571 *s++ = 'x';
572 *s++ = "0123456789abcdef"[c >> 4];
573 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574 }
575 } else {
576 for (i = 0; i < size; ++i) {
577 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000578 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200579 if (c == eol)
580 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000581 switch (c) {
582 case '\"': case '\\':
583 *s++ = '\\';
584 *s++ = c;
585 break;
586 case '\f':
587 *s++ = '\\';
588 *s++ = 'f';
589 break;
590 case '\n':
591 *s++ = '\\';
592 *s++ = 'n';
593 break;
594 case '\r':
595 *s++ = '\\';
596 *s++ = 'r';
597 break;
598 case '\t':
599 *s++ = '\\';
600 *s++ = 't';
601 break;
602 case '\v':
603 *s++ = '\\';
604 *s++ = 'v';
605 break;
606 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100607 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000608 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200609 else {
610 /* Print \octal */
611 *s++ = '\\';
612 if (i + 1 < size
613 && ustr[i + 1] >= '0'
614 && ustr[i + 1] <= '9'
615 ) {
616 /* Print \ooo */
617 *s++ = '0' + (c >> 6);
618 *s++ = '0' + ((c >> 3) & 0x7);
619 } else {
620 /* Print \[[o]o]o */
621 if ((c >> 3) != 0) {
622 if ((c >> 6) != 0)
623 *s++ = '0' + (c >> 6);
624 *s++ = '0' + ((c >> 3) & 0x7);
625 }
626 }
627 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000628 }
629 break;
630 }
631 }
632 }
633
634 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000635 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000636
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200637 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200638 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200639 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
640 * but next char is NUL.
641 */
642 return 0;
643 }
644
645 return 1;
646
647 asciz_ended:
648 *s++ = '\"';
649 *s = '\0';
650 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
651 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652}
653
Dmitry V. Levina501f142008-11-10 23:19:13 +0000654/*
655 * Print path string specified by address `addr' and length `n'.
656 * If path length exceeds `n', append `...' to the output.
657 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000658void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000659printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000660{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000661 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100662 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100663
Dmitry V. Levina501f142008-11-10 23:19:13 +0000664 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200665 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000666 return;
667 }
668
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100669 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000670 if (n > sizeof path - 1)
671 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000672
673 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100674 nul_seen = umovestr(tcp, addr, n + 1, path);
675 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676 tprintf("%#lx", addr);
677 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100678 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000679
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100680 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100681 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100682 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100683 string_quote(path, outstr, -1, n);
684 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100685 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100686 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687 }
688}
689
690void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000691printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100693 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000694 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000695}
696
Dmitry V. Levina501f142008-11-10 23:19:13 +0000697/*
698 * Print string specified by address `addr' and length `len'.
699 * If `len' < 0, treat the string as a NUL-terminated string.
700 * If string length exceeds `max_strlen', append `...' to the output.
701 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000702void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200703printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000704{
705 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000706 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000707 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100708 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709
710 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200711 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 return;
713 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000714 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200715 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000716 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
717
718 if (outstr_size / 4 != max_strlen)
719 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000720 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200721 if (!str)
722 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000723 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200724 if (!outstr)
725 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000727
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200728 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000729 /*
730 * Treat as a NUL-terminated string: fetch one byte more
731 * because string_quote() quotes one byte less.
732 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000733 size = max_strlen + 1;
734 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 tprintf("%#lx", addr);
736 return;
737 }
738 }
739 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200740 size = max_strlen;
741 if (size > (unsigned long)len)
742 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000743 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744 tprintf("%#lx", addr);
745 return;
746 }
747 }
748
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100749 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
750 * or we were requested to print more than -s NUM chars)...
751 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100752 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000753 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000754
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100755 tprints(outstr);
756 if (ellipsis)
757 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758}
759
John Hughes1d08dcf2001-07-10 13:48:44 +0000760void
Denys Vlasenko12014262011-05-30 14:00:14 +0200761dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000762{
Denys Vlasenko84703742012-02-25 02:38:52 +0100763#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000764 union {
765 struct { u_int32_t base; u_int32_t len; } *iov32;
766 struct { u_int64_t base; u_int64_t len; } *iov64;
767 } iovu;
768#define iov iovu.iov64
769#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100770 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000771#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100772 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000773#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100774 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000775#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000776 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000777#define sizeof_iov sizeof(*iov)
778#define iov_iov_base(i) iov[i].iov_base
779#define iov_iov_len(i) iov[i].iov_len
780#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000781 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200782 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000783
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200784 size = sizeof_iov * len;
785 /* Assuming no sane program has millions of iovs */
786 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000787 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200788 fprintf(stderr, "Out of memory\n");
789 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000790 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000791 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000792 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000793 /* include the buffer number to make it easy to
794 * match up the trace with the source */
795 tprintf(" * %lu bytes in buffer %d\n",
796 (unsigned long)iov_iov_len(i), i);
797 dumpstr(tcp, (long) iov_iov_base(i),
798 iov_iov_len(i));
799 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000800 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200801 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000802#undef sizeof_iov
803#undef iov_iov_base
804#undef iov_iov_len
805#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000806}
John Hughes1d08dcf2001-07-10 13:48:44 +0000807
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808void
Denys Vlasenko12014262011-05-30 14:00:14 +0200809dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000810{
811 static int strsize = -1;
812 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813
Denys Vlasenko76325802013-02-22 14:47:39 +0100814 char outbuf[
815 (
816 (sizeof(
817 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
818 "1234567890123456") + /*in case I'm off by few:*/ 4)
819 /*align to 8 to make memset easier:*/ + 7) & -8
820 ];
821 const unsigned char *src;
822 int i;
823
824 memset(outbuf, ' ', sizeof(outbuf));
825
826 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200827 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100828 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200829 if (!str) {
830 strsize = -1;
831 fprintf(stderr, "Out of memory\n");
832 return;
833 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100834 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000835 }
836
837 if (umoven(tcp, addr, len, (char *) str) < 0)
838 return;
839
Denys Vlasenko76325802013-02-22 14:47:39 +0100840 /* Space-pad to 16 bytes */
841 i = len;
842 while (i & 0xf)
843 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200844
Denys Vlasenko76325802013-02-22 14:47:39 +0100845 i = 0;
846 src = str;
847 while (i < len) {
848 char *dst = outbuf;
849 /* Hex dump */
850 do {
851 if (i < len) {
852 *dst++ = "0123456789abcdef"[*src >> 4];
853 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000854 }
855 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100856 *dst++ = ' ';
857 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100859 dst++; /* space is there by memset */
860 i++;
861 if ((i & 7) == 0)
862 dst++; /* space is there by memset */
863 src++;
864 } while (i & 0xf);
865 /* ASCII dump */
866 i -= 16;
867 src -= 16;
868 do {
869 if (*src >= ' ' && *src < 0x7f)
870 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100872 *dst++ = '.';
873 src++;
874 } while (++i & 0xf);
875 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100876 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000877 }
878}
879
Mike Frysinger612659e2012-02-14 14:38:28 +0100880#ifdef HAVE_PROCESS_VM_READV
881/* C library supports this, but the kernel might not. */
882static bool process_vm_readv_not_supported = 0;
883#else
884
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100885/* Need to do this since process_vm_readv() is not yet available in libc.
886 * When libc is be updated, only "static bool process_vm_readv_not_supported"
887 * line should remain.
888 */
889#if !defined(__NR_process_vm_readv)
890# if defined(I386)
891# define __NR_process_vm_readv 347
892# elif defined(X86_64)
893# define __NR_process_vm_readv 310
894# elif defined(POWERPC)
895# define __NR_process_vm_readv 351
896# endif
897#endif
898
899#if defined(__NR_process_vm_readv)
900static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400901/* Have to avoid duplicating with the C library headers. */
902static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100903 const struct iovec *lvec,
904 unsigned long liovcnt,
905 const struct iovec *rvec,
906 unsigned long riovcnt,
907 unsigned long flags)
908{
909 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
910}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400911#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100912#else
913static bool process_vm_readv_not_supported = 1;
914# define process_vm_readv(...) (errno = ENOSYS, -1)
915#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100916
917#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100918
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919#define PAGMASK (~(PAGSIZ - 1))
920/*
921 * move `len' bytes of data from process `pid'
922 * at address `addr' to our space at `laddr'
923 */
924int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000925umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700927 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000928 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000929 union {
930 long val;
931 char x[sizeof(long)];
932 } u;
933
Denys Vlasenko2544f982013-02-19 17:39:56 +0100934#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100935 if (current_wordsize < sizeof(addr))
936 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100937#endif
938
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100939 if (!process_vm_readv_not_supported) {
940 struct iovec local[1], remote[1];
941 int r;
942
943 local[0].iov_base = laddr;
944 remote[0].iov_base = (void*)addr;
945 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000946 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100947 if (r == len)
948 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000949 if (r >= 0) {
950 error_msg("umoven: short read (%d < %d) @0x%lx",
951 r, len, addr);
952 return -1;
953 }
954 switch (errno) {
955 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100956 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000957 break;
958 case ESRCH:
959 /* the process is gone */
960 return -1;
961 case EFAULT: case EIO: case EPERM:
962 /* address space is inaccessible */
963 return -1;
964 default:
965 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100966 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000967 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100968 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100969 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100970
Dmitry V. Levin97005922013-02-26 21:16:22 +0000971 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 if (addr & (sizeof(long) - 1)) {
973 /* addr not a multiple of sizeof(long) */
974 n = addr - (addr & -sizeof(long)); /* residue */
975 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700976 errno = 0;
977 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000978 switch (errno) {
979 case 0:
980 break;
981 case ESRCH: case EINVAL:
982 /* these could be seen if the process is gone */
983 return -1;
984 case EFAULT: case EIO: case EPERM:
985 /* address space is inaccessible */
986 return -1;
987 default:
988 /* all the rest is strange and should be reported */
989 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
990 pid, addr);
991 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700992 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100993 m = MIN(sizeof(long) - n, len);
994 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100995 addr += sizeof(long);
996 laddr += m;
997 nread += m;
998 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 }
1000 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001001 errno = 0;
1002 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001003 switch (errno) {
1004 case 0:
1005 break;
1006 case ESRCH: case EINVAL:
1007 /* these could be seen if the process is gone */
1008 return -1;
1009 case EFAULT: case EIO: case EPERM:
1010 /* address space is inaccessible */
1011 if (nread) {
1012 perror_msg("umoven: short read (%d < %d) @0x%lx",
1013 nread, nread + len, addr - nread);
1014 }
1015 return -1;
1016 default:
1017 /* all the rest is strange and should be reported */
1018 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1019 pid, addr);
1020 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001021 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001022 m = MIN(sizeof(long), len);
1023 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001024 addr += sizeof(long);
1025 laddr += m;
1026 nread += m;
1027 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030 return 0;
1031}
1032
1033/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001034 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001036 *
1037 * Returns < 0 on error, > 0 if NUL was seen,
1038 * (TODO if useful: return count of bytes including NUL),
1039 * else 0 if len bytes were read but no NUL byte seen.
1040 *
1041 * Note: there is no guarantee we won't overwrite some bytes
1042 * in laddr[] _after_ terminating NUL (but, of course,
1043 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044 */
1045int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001046umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047{
Denys Vlasenko16940922013-03-01 18:52:59 +01001048#if SIZEOF_LONG == 4
1049 const unsigned long x01010101 = 0x01010101ul;
1050 const unsigned long x80808080 = 0x80808080ul;
1051#elif SIZEOF_LONG == 8
1052 const unsigned long x01010101 = 0x0101010101010101ul;
1053 const unsigned long x80808080 = 0x8080808080808080ul;
1054#else
1055# error SIZEOF_LONG > 8
1056#endif
1057
Roland McGratheb9e2e82009-06-02 16:49:22 -07001058 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +01001059 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001061 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 char x[sizeof(long)];
1063 } u;
1064
Denys Vlasenko2544f982013-02-19 17:39:56 +01001065#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001066 if (current_wordsize < sizeof(addr))
1067 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001068#endif
1069
Dmitry V. Levin97005922013-02-26 21:16:22 +00001070 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001071 if (!process_vm_readv_not_supported) {
1072 struct iovec local[1], remote[1];
1073
1074 local[0].iov_base = laddr;
1075 remote[0].iov_base = (void*)addr;
1076
1077 while (len > 0) {
1078 int end_in_page;
1079 int r;
1080 int chunk_len;
1081
1082 /* Don't read kilobytes: most strings are short */
1083 chunk_len = len;
1084 if (chunk_len > 256)
1085 chunk_len = 256;
1086 /* Don't cross pages. I guess otherwise we can get EFAULT
1087 * and fail to notice that terminating NUL lies
1088 * in the existing (first) page.
1089 * (I hope there aren't arches with pages < 4K)
1090 */
1091 end_in_page = ((addr + chunk_len) & 4095);
1092 r = chunk_len - end_in_page;
1093 if (r > 0) /* if chunk_len > end_in_page */
1094 chunk_len = r; /* chunk_len -= end_in_page */
1095
1096 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001097 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1098 if (r > 0) {
1099 if (memchr(local[0].iov_base, '\0', r))
1100 return 1;
1101 local[0].iov_base += r;
1102 remote[0].iov_base += r;
1103 len -= r;
1104 nread += r;
1105 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001106 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001107 switch (errno) {
1108 case ENOSYS:
1109 process_vm_readv_not_supported = 1;
1110 goto vm_readv_didnt_work;
1111 case ESRCH:
1112 /* 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);
1119 }
1120 return -1;
1121 default:
1122 /* all the rest is strange and should be reported */
1123 perror_msg("process_vm_readv");
1124 return -1;
1125 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001126 }
1127 return 0;
1128 }
1129 vm_readv_didnt_work:
1130
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 if (addr & (sizeof(long) - 1)) {
1132 /* addr not a multiple of sizeof(long) */
1133 n = addr - (addr & -sizeof(long)); /* residue */
1134 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001135 errno = 0;
1136 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001137 switch (errno) {
1138 case 0:
1139 break;
1140 case ESRCH: case EINVAL:
1141 /* these could be seen if the process is gone */
1142 return -1;
1143 case EFAULT: case EIO: case EPERM:
1144 /* address space is inaccessible */
1145 return -1;
1146 default:
1147 /* all the rest is strange and should be reported */
1148 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1149 pid, addr);
1150 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001151 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001152 m = MIN(sizeof(long) - n, len);
1153 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 while (n & (sizeof(long) - 1))
1155 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001156 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001157 addr += sizeof(long);
1158 laddr += m;
1159 nread += m;
1160 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001164 errno = 0;
1165 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001166 switch (errno) {
1167 case 0:
1168 break;
1169 case ESRCH: case EINVAL:
1170 /* these could be seen if the process is gone */
1171 return -1;
1172 case EFAULT: case EIO: case EPERM:
1173 /* address space is inaccessible */
1174 if (nread) {
1175 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1176 nread, nread + len, addr - nread);
1177 }
1178 return -1;
1179 default:
1180 /* all the rest is strange and should be reported */
1181 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1182 pid, addr);
1183 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001184 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001185 m = MIN(sizeof(long), len);
1186 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001187 /* "If a NUL char exists in this word" */
1188 if ((u.val - x01010101) & ~u.val & x80808080)
1189 return 1;
1190 addr += sizeof(long);
1191 laddr += m;
1192 nread += m;
1193 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001195 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196}
1197
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001199upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200{
1201 long val;
1202
Roland McGratheb9e2e82009-06-02 16:49:22 -07001203 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001204 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001205 if (val == -1 && errno) {
1206 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001207 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001208 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001210 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 *res = val;
1212 return 0;
1213}
1214
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001215/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1216 * and PTRACE_O_TRACE[V]FORK for tracing children.
1217 * If you are adding a new arch which is only supported by newer kernels,
1218 * you most likely don't need to add any code below
1219 * beside a dummy "return 0" block in change_syscall().
1220 */
1221
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001222/*
1223 * These #if's are huge, please indent them correctly.
1224 * It's easy to get confused otherwise.
1225 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001227#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001228
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001229#ifndef CLONE_PTRACE
1230# define CLONE_PTRACE 0x00002000
1231#endif
1232#ifndef CLONE_VFORK
1233# define CLONE_VFORK 0x00004000
1234#endif
1235#ifndef CLONE_VM
1236# define CLONE_VM 0x00000100
1237#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001238
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001239#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001240
1241typedef unsigned long *arg_setup_state;
1242
1243static int
1244arg_setup(struct tcb *tcp, arg_setup_state *state)
1245{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001246 unsigned long cfm, sof, sol;
1247 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001249 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001250 /* Satisfy a false GCC warning. */
1251 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001252 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001253 }
Roland McGrath08267b82004-02-20 22:56:43 +00001254
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001255 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001256 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001257 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001258 return -1;
1259
1260 sof = (cfm >> 0) & 0x7f;
1261 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001262 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263
Jan Kratochvil1f942712008-08-06 21:38:52 +00001264 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265 return 0;
1266}
1267
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001268# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001271get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272{
Roland McGrath08267b82004-02-20 22:56:43 +00001273 int ret;
1274
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001275 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001276 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001277 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001278 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001279 (unsigned long) ia64_rse_skip_regs(*state, 0),
1280 sizeof(long), (void *) valp);
1281 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282}
1283
1284static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001285get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286{
Roland McGrath08267b82004-02-20 22:56:43 +00001287 int ret;
1288
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001289 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001290 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001291 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001292 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001293 (unsigned long) ia64_rse_skip_regs(*state, 1),
1294 sizeof(long), (void *) valp);
1295 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001297
1298static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001299set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001300{
Roland McGrath08267b82004-02-20 22:56:43 +00001301 int req = PTRACE_POKEDATA;
1302 void *ap;
1303
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001304 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001305 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1306 req = PTRACE_POKEUSER;
1307 } else
1308 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001309 errno = 0;
1310 ptrace(req, tcp->pid, ap, val);
1311 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001312}
1313
1314static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001315set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001316{
Roland McGrath08267b82004-02-20 22:56:43 +00001317 int req = PTRACE_POKEDATA;
1318 void *ap;
1319
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001320 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001321 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1322 req = PTRACE_POKEUSER;
1323 } else
1324 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001325 errno = 0;
1326 ptrace(req, tcp->pid, ap, val);
1327 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001328}
1329
Roland McGrathb659f872008-07-18 01:19:36 +00001330/* ia64 does not return the input arguments from functions (and syscalls)
1331 according to ia64 RSE (Register Stack Engine) behavior. */
1332
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001333# define restore_arg0(tcp, state, val) ((void) (state), 0)
1334# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001335
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001336#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001338# if defined(SPARC64)
1339# undef PTRACE_GETREGS
1340# define PTRACE_GETREGS PTRACE_GETREGS64
1341# undef PTRACE_SETREGS
1342# define PTRACE_SETREGS PTRACE_SETREGS64
1343# endif
1344
Mike Frysinger8566c502009-10-12 11:05:14 -04001345typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001346
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001347# define arg_setup(tcp, state) \
1348 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1349# define arg_finish_change(tcp, state) \
1350 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001352# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1353# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1354# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1355# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1356# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001358#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001359
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001360# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001361/* Note: this is only true for the `clone' system call, which handles
1362 arguments specially. We could as well say that its first two arguments
1363 are swapped relative to other architectures, but that would just be
1364 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001365# define arg0_offset PT_GPR3
1366# define arg1_offset PT_ORIGGPR2
1367# define restore_arg0(tcp, state, val) ((void) (state), 0)
1368# define restore_arg1(tcp, state, val) ((void) (state), 0)
1369# define arg0_index 1
1370# define arg1_index 0
1371# elif defined(ALPHA) || defined(MIPS)
1372# define arg0_offset REG_A0
1373# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001374# elif defined(POWERPC)
1375# define arg0_offset (sizeof(unsigned long)*PT_R3)
1376# define arg1_offset (sizeof(unsigned long)*PT_R4)
1377# define restore_arg0(tcp, state, val) ((void) (state), 0)
1378# elif defined(HPPA)
1379# define arg0_offset PT_GR26
1380# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001381# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001382# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1383# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1384# elif defined(SH)
1385# define arg0_offset (4*(REG_REG0+4))
1386# define arg1_offset (4*(REG_REG0+5))
1387# elif defined(SH64)
1388 /* ABI defines arg0 & 1 in r2 & r3 */
1389# define arg0_offset (REG_OFFSET+16)
1390# define arg1_offset (REG_OFFSET+24)
1391# define restore_arg0(tcp, state, val) 0
1392# elif defined CRISV10 || defined CRISV32
1393# define arg0_offset (4*PT_R11)
1394# define arg1_offset (4*PT_ORIG_R10)
1395# define restore_arg0(tcp, state, val) 0
1396# define restore_arg1(tcp, state, val) 0
1397# define arg0_index 1
1398# define arg1_index 0
1399# else
1400# define arg0_offset 0
1401# define arg1_offset 4
1402# if defined ARM
1403# define restore_arg0(tcp, state, val) 0
1404# endif
1405# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406
1407typedef int arg_setup_state;
1408
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001409# define arg_setup(tcp, state) (0)
1410# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001411# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1412# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413
1414static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001415set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001416{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001417 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001418}
1419
1420static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001421set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001423 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001424}
1425
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001426#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001428#ifndef restore_arg0
1429# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1430#endif
1431#ifndef restore_arg1
1432# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1433#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001434
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001435#ifndef arg0_index
1436# define arg0_index 0
1437# define arg1_index 1
1438#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001439
James Hogan05eb9052012-11-29 17:37:37 +00001440static int
1441change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1442{
1443#if defined(I386)
1444 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1445 return -1;
1446 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001447#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001448 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1449 return -1;
1450 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001451#elif defined(X32)
1452 /* setbpt/clearbpt never used: */
1453 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001454#elif defined(POWERPC)
1455 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1456 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1457 return -1;
1458 return 0;
1459#elif defined(S390) || defined(S390X)
1460 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1461 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1462 return -1;
1463 return 0;
1464#elif defined(M68K)
1465 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1466 return -1;
1467 return 0;
1468#elif defined(SPARC) || defined(SPARC64)
1469 state->u_regs[U_REG_G1] = new;
1470 return 0;
1471#elif defined(MIPS)
1472 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1473 return -1;
1474 return 0;
1475#elif defined(ALPHA)
1476 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1477 return -1;
1478 return 0;
1479#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001480 /* setbpt/clearbpt never used: */
1481 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001482#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001483 /* setbpt/clearbpt never used: */
1484 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001485#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001486 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001487 switch (new) {
1488 case 2:
1489 break; /* x86 SYS_fork */
1490 case SYS_clone:
1491 new = 120;
1492 break;
1493 default:
1494 fprintf(stderr, "%s: unexpected syscall %d\n",
1495 __FUNCTION__, new);
1496 return -1;
1497 }
1498 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1499 return -1;
1500 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1501 return -1;
1502 return 0;
1503#elif defined(HPPA)
1504 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1505 return -1;
1506 return 0;
1507#elif defined(SH)
1508 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1509 return -1;
1510 return 0;
1511#elif defined(SH64)
1512 /* Top half of reg encodes the no. of args n as 0x1n.
1513 Assume 0 args as kernel never actually checks... */
1514 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1515 0x100000 | new) < 0)
1516 return -1;
1517 return 0;
1518#elif defined(CRISV10) || defined(CRISV32)
1519 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1520 return -1;
1521 return 0;
1522#elif defined(ARM)
1523 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1524# ifndef PTRACE_SET_SYSCALL
1525# define PTRACE_SET_SYSCALL 23
1526# endif
1527 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1528 return -1;
1529 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001530#elif defined(AARCH64)
1531 /* setbpt/clearbpt never used: */
1532 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001533#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001534 /* setbpt/clearbpt never used: */
1535 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001536#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001537 /* setbpt/clearbpt never used: */
1538 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001539#elif defined(OR1K)
1540 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001541#elif defined(METAG)
1542 /* setbpt/clearbpt never used: */
1543 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001544#elif defined(XTENSA)
1545 /* setbpt/clearbpt never used: */
1546 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301547#elif defined(ARC)
1548 /* setbpt/clearbpt never used: */
1549 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001550#else
1551#warning Do not know how to handle change_syscall for this architecture
1552#endif /* architecture */
1553 return -1;
1554}
1555
Roland McGrathd81f1d92003-01-09 06:53:34 +00001556int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001557setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001558{
Roland McGrath3291ef22008-05-20 00:34:34 +00001559 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001560 arg_setup_state state;
1561
1562 if (tcp->flags & TCB_BPTSET) {
1563 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1564 return -1;
1565 }
1566
Roland McGrath3291ef22008-05-20 00:34:34 +00001567 /*
1568 * It's a silly kludge to initialize this with a search at runtime.
1569 * But it's better than maintaining another magic thing in the
1570 * godforsaken tables.
1571 */
1572 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001573 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001574 for (i = 0; i < nsyscalls; ++i)
1575 if (sysent[i].sys_func == sys_clone) {
1576 clone_scno[current_personality] = i;
1577 break;
1578 }
1579 }
1580
Dmitry V. Levin65563152014-05-12 13:43:10 +00001581 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001582 if (arg_setup(tcp, &state) < 0
1583 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1584 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001585 || change_syscall(tcp, &state,
1586 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001587 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1588 || set_arg1(tcp, &state, 0) < 0
1589 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001590 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001591 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1592 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001593 tcp->flags |= TCB_BPTSET;
1594 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001595 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001596
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001597 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001598 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001599 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001600 vfork semantics into plain fork - each application must not
1601 depend on the vfork specifics according to POSIX. We would
1602 hang waiting for the parent resume otherwise. We need to
1603 clear also CLONE_VM but only in the CLONE_VFORK case as
1604 otherwise we would break pthread_create. */
1605
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001606 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1607 if (new_arg0 & CLONE_VFORK)
1608 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1609 if (arg_setup(tcp, &state) < 0
1610 || set_arg0(tcp, &state, new_arg0) < 0
1611 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001612 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001613 tcp->inst[0] = tcp->u_arg[arg0_index];
1614 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001615 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001616 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001617 }
1618
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001619 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1620 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001621 return -1;
1622}
1623
1624int
Denys Vlasenko12014262011-05-30 14:00:14 +02001625clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001626{
1627 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001628 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001629 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001630 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1631 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1632 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001633 if (errno != ESRCH)
1634 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001635 tcp->flags &= ~TCB_BPTSET;
1636 return 0;
1637}