blob: 570888c8685dc749cc29606f6c6189637465263c [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;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000428 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000429
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;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900485#define PROTO_NAME_LEN 32
486 char proto_buf[PROTO_NAME_LEN];
487 const char *proto =
488 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000489 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
490 tprintf("%d<", fd);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900491 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900492 if (proto)
493 tprintf("%s:[%lu]", proto, inodenr);
494 else
495 tprints(path);
496 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000497 tprints(">");
498 } else {
499 tprintf("%d<%s>", fd, path);
500 }
501 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000502 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300503}
504
Dmitry V. Levina501f142008-11-10 23:19:13 +0000505/*
506 * Quote string `instr' of length `size'
507 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200508 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000509 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100510 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200511 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100512 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000513 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400514int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200515string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000517 const unsigned char *ustr = (const unsigned char *) instr;
518 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200519 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200521 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200522 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200523 size--;
524 eol = '\0';
525 }
526
527 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528 if (xflag > 1)
529 usehex = 1;
530 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000531 /* Check for presence of symbol which require
532 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000533 for (i = 0; i < size; ++i) {
534 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000535 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200536 if (c == eol)
537 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100538
539 /* Force hex unless c is printable or whitespace */
540 if (c > 0x7e) {
541 usehex = 1;
542 break;
543 }
544 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
545 * They happen to have ASCII codes 9,10,11,12,13.
546 */
547 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000548 usehex = 1;
549 break;
550 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 }
552 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553
554 *s++ = '\"';
555
556 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000557 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000558 for (i = 0; i < size; ++i) {
559 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000560 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200561 if (c == eol)
562 goto asciz_ended;
563 *s++ = '\\';
564 *s++ = 'x';
565 *s++ = "0123456789abcdef"[c >> 4];
566 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567 }
568 } else {
569 for (i = 0; i < size; ++i) {
570 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000571 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200572 if (c == eol)
573 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574 switch (c) {
575 case '\"': case '\\':
576 *s++ = '\\';
577 *s++ = c;
578 break;
579 case '\f':
580 *s++ = '\\';
581 *s++ = 'f';
582 break;
583 case '\n':
584 *s++ = '\\';
585 *s++ = 'n';
586 break;
587 case '\r':
588 *s++ = '\\';
589 *s++ = 'r';
590 break;
591 case '\t':
592 *s++ = '\\';
593 *s++ = 't';
594 break;
595 case '\v':
596 *s++ = '\\';
597 *s++ = 'v';
598 break;
599 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100600 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000601 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200602 else {
603 /* Print \octal */
604 *s++ = '\\';
605 if (i + 1 < size
606 && ustr[i + 1] >= '0'
607 && ustr[i + 1] <= '9'
608 ) {
609 /* Print \ooo */
610 *s++ = '0' + (c >> 6);
611 *s++ = '0' + ((c >> 3) & 0x7);
612 } else {
613 /* Print \[[o]o]o */
614 if ((c >> 3) != 0) {
615 if ((c >> 6) != 0)
616 *s++ = '0' + (c >> 6);
617 *s++ = '0' + ((c >> 3) & 0x7);
618 }
619 }
620 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000621 }
622 break;
623 }
624 }
625 }
626
627 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000629
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200630 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200631 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200632 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
633 * but next char is NUL.
634 */
635 return 0;
636 }
637
638 return 1;
639
640 asciz_ended:
641 *s++ = '\"';
642 *s = '\0';
643 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
644 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645}
646
Dmitry V. Levina501f142008-11-10 23:19:13 +0000647/*
648 * Print path string specified by address `addr' and length `n'.
649 * If path length exceeds `n', append `...' to the output.
650 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000652printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000654 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100655 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100656
Dmitry V. Levina501f142008-11-10 23:19:13 +0000657 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200658 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000659 return;
660 }
661
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100662 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000663 if (n > sizeof path - 1)
664 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000665
666 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100667 nul_seen = umovestr(tcp, addr, n + 1, path);
668 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669 tprintf("%#lx", addr);
670 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100671 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000672
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100673 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100674 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100675 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100676 string_quote(path, outstr, -1, n);
677 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100678 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100679 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680 }
681}
682
683void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000684printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100686 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000687 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000688}
689
Dmitry V. Levina501f142008-11-10 23:19:13 +0000690/*
691 * Print string specified by address `addr' and length `len'.
692 * If `len' < 0, treat the string as a NUL-terminated string.
693 * If string length exceeds `max_strlen', append `...' to the output.
694 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000695void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200696printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000697{
698 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000700 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100701 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000702
703 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200704 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 return;
706 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000707 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200708 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000709 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
710
711 if (outstr_size / 4 != max_strlen)
712 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000713 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200714 if (!str)
715 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000716 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200717 if (!outstr)
718 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000720
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200721 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000722 /*
723 * Treat as a NUL-terminated string: fetch one byte more
724 * because string_quote() quotes one byte less.
725 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000726 size = max_strlen + 1;
727 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 tprintf("%#lx", addr);
729 return;
730 }
731 }
732 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200733 size = max_strlen;
734 if (size > (unsigned long)len)
735 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000736 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737 tprintf("%#lx", addr);
738 return;
739 }
740 }
741
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100742 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
743 * or we were requested to print more than -s NUM chars)...
744 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100745 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000746 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000747
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100748 tprints(outstr);
749 if (ellipsis)
750 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751}
752
John Hughes1d08dcf2001-07-10 13:48:44 +0000753void
Denys Vlasenko12014262011-05-30 14:00:14 +0200754dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000755{
Denys Vlasenko84703742012-02-25 02:38:52 +0100756#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000757 union {
758 struct { u_int32_t base; u_int32_t len; } *iov32;
759 struct { u_int64_t base; u_int64_t len; } *iov64;
760 } iovu;
761#define iov iovu.iov64
762#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100763 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000764#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100765 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000766#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100767 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000768#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000769 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000770#define sizeof_iov sizeof(*iov)
771#define iov_iov_base(i) iov[i].iov_base
772#define iov_iov_len(i) iov[i].iov_len
773#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000774 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200775 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000776
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200777 size = sizeof_iov * len;
778 /* Assuming no sane program has millions of iovs */
779 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000780 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200781 fprintf(stderr, "Out of memory\n");
782 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000783 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000784 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000785 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000786 /* include the buffer number to make it easy to
787 * match up the trace with the source */
788 tprintf(" * %lu bytes in buffer %d\n",
789 (unsigned long)iov_iov_len(i), i);
790 dumpstr(tcp, (long) iov_iov_base(i),
791 iov_iov_len(i));
792 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000793 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200794 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000795#undef sizeof_iov
796#undef iov_iov_base
797#undef iov_iov_len
798#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000799}
John Hughes1d08dcf2001-07-10 13:48:44 +0000800
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801void
Denys Vlasenko12014262011-05-30 14:00:14 +0200802dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803{
804 static int strsize = -1;
805 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806
Denys Vlasenko76325802013-02-22 14:47:39 +0100807 char outbuf[
808 (
809 (sizeof(
810 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
811 "1234567890123456") + /*in case I'm off by few:*/ 4)
812 /*align to 8 to make memset easier:*/ + 7) & -8
813 ];
814 const unsigned char *src;
815 int i;
816
817 memset(outbuf, ' ', sizeof(outbuf));
818
819 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200820 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100821 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200822 if (!str) {
823 strsize = -1;
824 fprintf(stderr, "Out of memory\n");
825 return;
826 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100827 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 }
829
830 if (umoven(tcp, addr, len, (char *) str) < 0)
831 return;
832
Denys Vlasenko76325802013-02-22 14:47:39 +0100833 /* Space-pad to 16 bytes */
834 i = len;
835 while (i & 0xf)
836 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200837
Denys Vlasenko76325802013-02-22 14:47:39 +0100838 i = 0;
839 src = str;
840 while (i < len) {
841 char *dst = outbuf;
842 /* Hex dump */
843 do {
844 if (i < len) {
845 *dst++ = "0123456789abcdef"[*src >> 4];
846 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 }
848 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100849 *dst++ = ' ';
850 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100852 dst++; /* space is there by memset */
853 i++;
854 if ((i & 7) == 0)
855 dst++; /* space is there by memset */
856 src++;
857 } while (i & 0xf);
858 /* ASCII dump */
859 i -= 16;
860 src -= 16;
861 do {
862 if (*src >= ' ' && *src < 0x7f)
863 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100865 *dst++ = '.';
866 src++;
867 } while (++i & 0xf);
868 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100869 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870 }
871}
872
Mike Frysinger612659e2012-02-14 14:38:28 +0100873#ifdef HAVE_PROCESS_VM_READV
874/* C library supports this, but the kernel might not. */
875static bool process_vm_readv_not_supported = 0;
876#else
877
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100878/* Need to do this since process_vm_readv() is not yet available in libc.
879 * When libc is be updated, only "static bool process_vm_readv_not_supported"
880 * line should remain.
881 */
882#if !defined(__NR_process_vm_readv)
883# if defined(I386)
884# define __NR_process_vm_readv 347
885# elif defined(X86_64)
886# define __NR_process_vm_readv 310
887# elif defined(POWERPC)
888# define __NR_process_vm_readv 351
889# endif
890#endif
891
892#if defined(__NR_process_vm_readv)
893static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400894/* Have to avoid duplicating with the C library headers. */
895static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100896 const struct iovec *lvec,
897 unsigned long liovcnt,
898 const struct iovec *rvec,
899 unsigned long riovcnt,
900 unsigned long flags)
901{
902 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
903}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400904#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100905#else
906static bool process_vm_readv_not_supported = 1;
907# define process_vm_readv(...) (errno = ENOSYS, -1)
908#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100909
910#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100911
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912#define PAGMASK (~(PAGSIZ - 1))
913/*
914 * move `len' bytes of data from process `pid'
915 * at address `addr' to our space at `laddr'
916 */
917int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000918umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700920 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000921 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 union {
923 long val;
924 char x[sizeof(long)];
925 } u;
926
Denys Vlasenko2544f982013-02-19 17:39:56 +0100927#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100928 if (current_wordsize < sizeof(addr))
929 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100930#endif
931
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100932 if (!process_vm_readv_not_supported) {
933 struct iovec local[1], remote[1];
934 int r;
935
936 local[0].iov_base = laddr;
937 remote[0].iov_base = (void*)addr;
938 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000939 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100940 if (r == len)
941 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000942 if (r >= 0) {
943 error_msg("umoven: short read (%d < %d) @0x%lx",
944 r, len, addr);
945 return -1;
946 }
947 switch (errno) {
948 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100949 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000950 break;
951 case ESRCH:
952 /* the process is gone */
953 return -1;
954 case EFAULT: case EIO: case EPERM:
955 /* address space is inaccessible */
956 return -1;
957 default:
958 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100959 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000960 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100961 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100962 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100963
Dmitry V. Levin97005922013-02-26 21:16:22 +0000964 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 if (addr & (sizeof(long) - 1)) {
966 /* addr not a multiple of sizeof(long) */
967 n = addr - (addr & -sizeof(long)); /* residue */
968 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700969 errno = 0;
970 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000971 switch (errno) {
972 case 0:
973 break;
974 case ESRCH: case EINVAL:
975 /* these could be seen if the process is gone */
976 return -1;
977 case EFAULT: case EIO: case EPERM:
978 /* address space is inaccessible */
979 return -1;
980 default:
981 /* all the rest is strange and should be reported */
982 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
983 pid, addr);
984 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700985 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100986 m = MIN(sizeof(long) - n, len);
987 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100988 addr += sizeof(long);
989 laddr += m;
990 nread += m;
991 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 }
993 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700994 errno = 0;
995 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000996 switch (errno) {
997 case 0:
998 break;
999 case ESRCH: case EINVAL:
1000 /* these could be seen if the process is gone */
1001 return -1;
1002 case EFAULT: case EIO: case EPERM:
1003 /* address space is inaccessible */
1004 if (nread) {
1005 perror_msg("umoven: short read (%d < %d) @0x%lx",
1006 nread, nread + len, addr - nread);
1007 }
1008 return -1;
1009 default:
1010 /* all the rest is strange and should be reported */
1011 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1012 pid, addr);
1013 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001014 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001015 m = MIN(sizeof(long), len);
1016 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001017 addr += sizeof(long);
1018 laddr += m;
1019 nread += m;
1020 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 return 0;
1024}
1025
1026/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001027 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001029 *
1030 * Returns < 0 on error, > 0 if NUL was seen,
1031 * (TODO if useful: return count of bytes including NUL),
1032 * else 0 if len bytes were read but no NUL byte seen.
1033 *
1034 * Note: there is no guarantee we won't overwrite some bytes
1035 * in laddr[] _after_ terminating NUL (but, of course,
1036 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 */
1038int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001039umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040{
Denys Vlasenko16940922013-03-01 18:52:59 +01001041#if SIZEOF_LONG == 4
1042 const unsigned long x01010101 = 0x01010101ul;
1043 const unsigned long x80808080 = 0x80808080ul;
1044#elif SIZEOF_LONG == 8
1045 const unsigned long x01010101 = 0x0101010101010101ul;
1046 const unsigned long x80808080 = 0x8080808080808080ul;
1047#else
1048# error SIZEOF_LONG > 8
1049#endif
1050
Roland McGratheb9e2e82009-06-02 16:49:22 -07001051 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +01001052 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001054 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 char x[sizeof(long)];
1056 } u;
1057
Denys Vlasenko2544f982013-02-19 17:39:56 +01001058#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001059 if (current_wordsize < sizeof(addr))
1060 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001061#endif
1062
Dmitry V. Levin97005922013-02-26 21:16:22 +00001063 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001064 if (!process_vm_readv_not_supported) {
1065 struct iovec local[1], remote[1];
1066
1067 local[0].iov_base = laddr;
1068 remote[0].iov_base = (void*)addr;
1069
1070 while (len > 0) {
1071 int end_in_page;
1072 int r;
1073 int chunk_len;
1074
1075 /* Don't read kilobytes: most strings are short */
1076 chunk_len = len;
1077 if (chunk_len > 256)
1078 chunk_len = 256;
1079 /* Don't cross pages. I guess otherwise we can get EFAULT
1080 * and fail to notice that terminating NUL lies
1081 * in the existing (first) page.
1082 * (I hope there aren't arches with pages < 4K)
1083 */
1084 end_in_page = ((addr + chunk_len) & 4095);
1085 r = chunk_len - end_in_page;
1086 if (r > 0) /* if chunk_len > end_in_page */
1087 chunk_len = r; /* chunk_len -= end_in_page */
1088
1089 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001090 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1091 if (r > 0) {
1092 if (memchr(local[0].iov_base, '\0', r))
1093 return 1;
1094 local[0].iov_base += r;
1095 remote[0].iov_base += r;
1096 len -= r;
1097 nread += r;
1098 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001099 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001100 switch (errno) {
1101 case ENOSYS:
1102 process_vm_readv_not_supported = 1;
1103 goto vm_readv_didnt_work;
1104 case ESRCH:
1105 /* the process is gone */
1106 return -1;
1107 case EFAULT: case EIO: case EPERM:
1108 /* address space is inaccessible */
1109 if (nread) {
1110 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1111 nread, nread + len, addr);
1112 }
1113 return -1;
1114 default:
1115 /* all the rest is strange and should be reported */
1116 perror_msg("process_vm_readv");
1117 return -1;
1118 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001119 }
1120 return 0;
1121 }
1122 vm_readv_didnt_work:
1123
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 if (addr & (sizeof(long) - 1)) {
1125 /* addr not a multiple of sizeof(long) */
1126 n = addr - (addr & -sizeof(long)); /* residue */
1127 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001128 errno = 0;
1129 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001130 switch (errno) {
1131 case 0:
1132 break;
1133 case ESRCH: case EINVAL:
1134 /* these could be seen if the process is gone */
1135 return -1;
1136 case EFAULT: case EIO: case EPERM:
1137 /* address space is inaccessible */
1138 return -1;
1139 default:
1140 /* all the rest is strange and should be reported */
1141 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1142 pid, addr);
1143 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001144 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001145 m = MIN(sizeof(long) - n, len);
1146 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 while (n & (sizeof(long) - 1))
1148 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001149 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001150 addr += sizeof(long);
1151 laddr += m;
1152 nread += m;
1153 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001155
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001157 errno = 0;
1158 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001159 switch (errno) {
1160 case 0:
1161 break;
1162 case ESRCH: case EINVAL:
1163 /* these could be seen if the process is gone */
1164 return -1;
1165 case EFAULT: case EIO: case EPERM:
1166 /* address space is inaccessible */
1167 if (nread) {
1168 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1169 nread, nread + len, addr - nread);
1170 }
1171 return -1;
1172 default:
1173 /* all the rest is strange and should be reported */
1174 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1175 pid, addr);
1176 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001177 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001178 m = MIN(sizeof(long), len);
1179 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001180 /* "If a NUL char exists in this word" */
1181 if ((u.val - x01010101) & ~u.val & x80808080)
1182 return 1;
1183 addr += sizeof(long);
1184 laddr += m;
1185 nread += m;
1186 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001188 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189}
1190
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001192upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193{
1194 long val;
1195
Roland McGratheb9e2e82009-06-02 16:49:22 -07001196 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001197 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001198 if (val == -1 && errno) {
1199 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001200 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001201 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001203 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 *res = val;
1205 return 0;
1206}
1207
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001208/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1209 * and PTRACE_O_TRACE[V]FORK for tracing children.
1210 * If you are adding a new arch which is only supported by newer kernels,
1211 * you most likely don't need to add any code below
1212 * beside a dummy "return 0" block in change_syscall().
1213 */
1214
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001215/*
1216 * These #if's are huge, please indent them correctly.
1217 * It's easy to get confused otherwise.
1218 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001220#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001221
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001222#ifndef CLONE_PTRACE
1223# define CLONE_PTRACE 0x00002000
1224#endif
1225#ifndef CLONE_VFORK
1226# define CLONE_VFORK 0x00004000
1227#endif
1228#ifndef CLONE_VM
1229# define CLONE_VM 0x00000100
1230#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001231
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001232#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001233
1234typedef unsigned long *arg_setup_state;
1235
1236static int
1237arg_setup(struct tcb *tcp, arg_setup_state *state)
1238{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001239 unsigned long cfm, sof, sol;
1240 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001241
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001242 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001243 /* Satisfy a false GCC warning. */
1244 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001245 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001246 }
Roland McGrath08267b82004-02-20 22:56:43 +00001247
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001248 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001249 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001250 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001251 return -1;
1252
1253 sof = (cfm >> 0) & 0x7f;
1254 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001255 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001256
Jan Kratochvil1f942712008-08-06 21:38:52 +00001257 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001258 return 0;
1259}
1260
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001261# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001264get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265{
Roland McGrath08267b82004-02-20 22:56:43 +00001266 int ret;
1267
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001268 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001269 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001270 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001271 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001272 (unsigned long) ia64_rse_skip_regs(*state, 0),
1273 sizeof(long), (void *) valp);
1274 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275}
1276
1277static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001278get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279{
Roland McGrath08267b82004-02-20 22:56:43 +00001280 int ret;
1281
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001282 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001283 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001284 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001285 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001286 (unsigned long) ia64_rse_skip_regs(*state, 1),
1287 sizeof(long), (void *) valp);
1288 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001289}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290
1291static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001292set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001293{
Roland McGrath08267b82004-02-20 22:56:43 +00001294 int req = PTRACE_POKEDATA;
1295 void *ap;
1296
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001297 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001298 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1299 req = PTRACE_POKEUSER;
1300 } else
1301 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001302 errno = 0;
1303 ptrace(req, tcp->pid, ap, val);
1304 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001305}
1306
1307static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001308set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001309{
Roland McGrath08267b82004-02-20 22:56:43 +00001310 int req = PTRACE_POKEDATA;
1311 void *ap;
1312
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001313 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001314 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1315 req = PTRACE_POKEUSER;
1316 } else
1317 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001318 errno = 0;
1319 ptrace(req, tcp->pid, ap, val);
1320 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001321}
1322
Roland McGrathb659f872008-07-18 01:19:36 +00001323/* ia64 does not return the input arguments from functions (and syscalls)
1324 according to ia64 RSE (Register Stack Engine) behavior. */
1325
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001326# define restore_arg0(tcp, state, val) ((void) (state), 0)
1327# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001328
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001329#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001331# if defined(SPARC64)
1332# undef PTRACE_GETREGS
1333# define PTRACE_GETREGS PTRACE_GETREGS64
1334# undef PTRACE_SETREGS
1335# define PTRACE_SETREGS PTRACE_SETREGS64
1336# endif
1337
Mike Frysinger8566c502009-10-12 11:05:14 -04001338typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001340# define arg_setup(tcp, state) \
1341 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1342# define arg_finish_change(tcp, state) \
1343 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001344
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001345# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1346# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1347# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1348# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1349# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001350
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001351#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001353# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001354/* Note: this is only true for the `clone' system call, which handles
1355 arguments specially. We could as well say that its first two arguments
1356 are swapped relative to other architectures, but that would just be
1357 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001358# define arg0_offset PT_GPR3
1359# define arg1_offset PT_ORIGGPR2
1360# define restore_arg0(tcp, state, val) ((void) (state), 0)
1361# define restore_arg1(tcp, state, val) ((void) (state), 0)
1362# define arg0_index 1
1363# define arg1_index 0
1364# elif defined(ALPHA) || defined(MIPS)
1365# define arg0_offset REG_A0
1366# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001367# elif defined(POWERPC)
1368# define arg0_offset (sizeof(unsigned long)*PT_R3)
1369# define arg1_offset (sizeof(unsigned long)*PT_R4)
1370# define restore_arg0(tcp, state, val) ((void) (state), 0)
1371# elif defined(HPPA)
1372# define arg0_offset PT_GR26
1373# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001374# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001375# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1376# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1377# elif defined(SH)
1378# define arg0_offset (4*(REG_REG0+4))
1379# define arg1_offset (4*(REG_REG0+5))
1380# elif defined(SH64)
1381 /* ABI defines arg0 & 1 in r2 & r3 */
1382# define arg0_offset (REG_OFFSET+16)
1383# define arg1_offset (REG_OFFSET+24)
1384# define restore_arg0(tcp, state, val) 0
1385# elif defined CRISV10 || defined CRISV32
1386# define arg0_offset (4*PT_R11)
1387# define arg1_offset (4*PT_ORIG_R10)
1388# define restore_arg0(tcp, state, val) 0
1389# define restore_arg1(tcp, state, val) 0
1390# define arg0_index 1
1391# define arg1_index 0
1392# else
1393# define arg0_offset 0
1394# define arg1_offset 4
1395# if defined ARM
1396# define restore_arg0(tcp, state, val) 0
1397# endif
1398# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001399
1400typedef int arg_setup_state;
1401
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001402# define arg_setup(tcp, state) (0)
1403# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001404# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1405# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406
1407static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001408set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001409{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001410 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411}
1412
1413static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001414set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001415{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001416 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417}
1418
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001419#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001421#ifndef restore_arg0
1422# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1423#endif
1424#ifndef restore_arg1
1425# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1426#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001428#ifndef arg0_index
1429# define arg0_index 0
1430# define arg1_index 1
1431#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001432
James Hogan05eb9052012-11-29 17:37:37 +00001433static int
1434change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1435{
1436#if defined(I386)
1437 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1438 return -1;
1439 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001440#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001441 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1442 return -1;
1443 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001444#elif defined(X32)
1445 /* setbpt/clearbpt never used: */
1446 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001447#elif defined(POWERPC)
1448 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1449 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1450 return -1;
1451 return 0;
1452#elif defined(S390) || defined(S390X)
1453 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1454 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1455 return -1;
1456 return 0;
1457#elif defined(M68K)
1458 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1459 return -1;
1460 return 0;
1461#elif defined(SPARC) || defined(SPARC64)
1462 state->u_regs[U_REG_G1] = new;
1463 return 0;
1464#elif defined(MIPS)
1465 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1466 return -1;
1467 return 0;
1468#elif defined(ALPHA)
1469 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1470 return -1;
1471 return 0;
1472#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001473 /* setbpt/clearbpt never used: */
1474 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001475#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001476 /* setbpt/clearbpt never used: */
1477 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001478#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001479 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001480 switch (new) {
1481 case 2:
1482 break; /* x86 SYS_fork */
1483 case SYS_clone:
1484 new = 120;
1485 break;
1486 default:
1487 fprintf(stderr, "%s: unexpected syscall %d\n",
1488 __FUNCTION__, new);
1489 return -1;
1490 }
1491 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1492 return -1;
1493 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1494 return -1;
1495 return 0;
1496#elif defined(HPPA)
1497 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1498 return -1;
1499 return 0;
1500#elif defined(SH)
1501 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1502 return -1;
1503 return 0;
1504#elif defined(SH64)
1505 /* Top half of reg encodes the no. of args n as 0x1n.
1506 Assume 0 args as kernel never actually checks... */
1507 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1508 0x100000 | new) < 0)
1509 return -1;
1510 return 0;
1511#elif defined(CRISV10) || defined(CRISV32)
1512 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1513 return -1;
1514 return 0;
1515#elif defined(ARM)
1516 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1517# ifndef PTRACE_SET_SYSCALL
1518# define PTRACE_SET_SYSCALL 23
1519# endif
1520 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1521 return -1;
1522 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001523#elif defined(AARCH64)
1524 /* setbpt/clearbpt never used: */
1525 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001526#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001527 /* setbpt/clearbpt never used: */
1528 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001529#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001530 /* setbpt/clearbpt never used: */
1531 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001532#elif defined(OR1K)
1533 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001534#elif defined(METAG)
1535 /* setbpt/clearbpt never used: */
1536 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001537#elif defined(XTENSA)
1538 /* setbpt/clearbpt never used: */
1539 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301540#elif defined(ARC)
1541 /* setbpt/clearbpt never used: */
1542 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001543#else
1544#warning Do not know how to handle change_syscall for this architecture
1545#endif /* architecture */
1546 return -1;
1547}
1548
Roland McGrathd81f1d92003-01-09 06:53:34 +00001549int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001550setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001551{
Roland McGrath3291ef22008-05-20 00:34:34 +00001552 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001553 arg_setup_state state;
1554
1555 if (tcp->flags & TCB_BPTSET) {
1556 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1557 return -1;
1558 }
1559
Roland McGrath3291ef22008-05-20 00:34:34 +00001560 /*
1561 * It's a silly kludge to initialize this with a search at runtime.
1562 * But it's better than maintaining another magic thing in the
1563 * godforsaken tables.
1564 */
1565 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001566 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001567 for (i = 0; i < nsyscalls; ++i)
1568 if (sysent[i].sys_func == sys_clone) {
1569 clone_scno[current_personality] = i;
1570 break;
1571 }
1572 }
1573
Dmitry V. Levin65563152014-05-12 13:43:10 +00001574 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001575 if (arg_setup(tcp, &state) < 0
1576 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1577 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001578 || change_syscall(tcp, &state,
1579 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001580 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1581 || set_arg1(tcp, &state, 0) < 0
1582 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001583 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001584 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1585 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001586 tcp->flags |= TCB_BPTSET;
1587 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001588 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001589
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001590 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001591 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001592 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001593 vfork semantics into plain fork - each application must not
1594 depend on the vfork specifics according to POSIX. We would
1595 hang waiting for the parent resume otherwise. We need to
1596 clear also CLONE_VM but only in the CLONE_VFORK case as
1597 otherwise we would break pthread_create. */
1598
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001599 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1600 if (new_arg0 & CLONE_VFORK)
1601 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1602 if (arg_setup(tcp, &state) < 0
1603 || set_arg0(tcp, &state, new_arg0) < 0
1604 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001605 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001606 tcp->inst[0] = tcp->u_arg[arg0_index];
1607 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001608 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001609 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001610 }
1611
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001612 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1613 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001614 return -1;
1615}
1616
1617int
Denys Vlasenko12014262011-05-30 14:00:14 +02001618clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001619{
1620 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001621 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001622 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001623 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1624 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1625 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001626 if (errno != ESRCH)
1627 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001628 tcp->flags &= ~TCB_BPTSET;
1629 return 0;
1630}