blob: 3b50191d9b7adf3ef9e570736afd16fcb97b386d [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/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000245 * Fetch 64bit argument at position arg_no and
246 * return the index of the next argument.
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100247 */
248int
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000249getllval(struct tcb *tcp, unsigned long long *val, 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
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000255 *val = tcp->u_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100256 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. Levin1ea64732015-01-10 00:08:58 +0000262# endif /* AARCH64 || POWERPC64 */
263 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100264 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100265 }
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000266# endif /* SUPPORTED_PERSONALITIES > 1 */
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000267#elif SIZEOF_LONG > 4
268# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
269#elif defined LINUX_MIPSN32
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000270 *val = 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) {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000274 *val = tcp->ext_arg[arg_no];
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000275 arg_no++;
276 } else {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000277 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000278 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
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000288 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100289 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/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000296 * Print 64bit argument at position arg_no and
297 * return the index of the next argument.
298 */
299int
300printllval(struct tcb *tcp, const char *format, int arg_no)
301{
302 unsigned long long val = 0;
303
304 arg_no = getllval(tcp, &val, arg_no);
305 tprintf(format, val);
306 return arg_no;
307}
308
309/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310 * Interpret `xlat' as an array of flags
311 * print the entries whose bits are on in `flags'
312 * return # of flags printed.
313 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200314void
Denys Vlasenko12014262011-05-30 14:00:14 +0200315addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200317 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318 if (xlat->val && (flags & xlat->val) == xlat->val) {
319 tprintf("|%s", xlat->str);
320 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 }
322 }
323 if (flags) {
324 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326}
327
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000328/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200329 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000330 * Print to static string the entries whose bits are on in `flags'
331 * Return static string.
332 */
333const char *
334sprintflags(const char *prefix, const struct xlat *xlat, int flags)
335{
336 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200337 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000338 int found = 0;
339
Denys Vlasenko52845572011-08-31 12:07:38 +0200340 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000341
342 for (; xlat->str; xlat++) {
343 if ((flags & xlat->val) == xlat->val) {
344 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200345 *outptr++ = '|';
346 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000347 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100348 flags &= ~xlat->val;
349 if (!flags)
350 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000351 }
352 }
353 if (flags) {
354 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200355 *outptr++ = '|';
356 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000357 }
358
359 return outstr;
360}
361
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000362int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000363printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364{
365 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000366 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000367
368 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200369 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370 return 1;
371 }
372
373 sep = "";
374 for (n = 0; xlat->str; xlat++) {
375 if (xlat->val && (flags & xlat->val) == xlat->val) {
376 tprintf("%s%s", sep, xlat->str);
377 flags &= ~xlat->val;
378 sep = "|";
379 n++;
380 }
381 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000382
383 if (n) {
384 if (flags) {
385 tprintf("%s%#x", sep, flags);
386 n++;
387 }
388 } else {
389 if (flags) {
390 tprintf("%#x", flags);
391 if (dflt)
392 tprintf(" /* %s */", dflt);
393 } else {
394 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200395 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000396 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000398
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000399 return n;
400}
401
402void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000403printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404{
Roland McGratheb285352003-01-14 09:59:00 +0000405 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000406
407 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200408 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 return;
410 }
411 if (umove(tcp, addr, &num) < 0) {
412 tprintf("%#lx", addr);
413 return;
414 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200415 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200417 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000418}
419
Roland McGrath6bc12202003-11-13 22:32:27 +0000420void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000421printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000422{
423 int num;
424
425 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200426 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000427 return;
428 }
429 if (umove(tcp, addr, &num) < 0) {
430 tprintf("%#lx", addr);
431 return;
432 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200433 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000434 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200435 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000436}
437
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000438const char *
439sprinttime(time_t t)
440{
441 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000442 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000443
444 if (t == 0) {
445 strcpy(buf, "0");
446 return buf;
447 }
448 tmp = localtime(&t);
449 if (tmp)
450 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
451 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
452 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
453 else
454 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
455
456 return buf;
457}
458
Masatake YAMATOf5480672014-11-22 19:03:33 +0900459static char *
460getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
461{
462#if HAVE_SYS_XATTR_H
463 ssize_t r;
464 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
465
466 if (fd < 0)
467 return NULL;
468
469 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
470 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
471 if (r <= 0)
472 return NULL;
473 else {
474 /*
475 * This is a protection for the case when the kernel
476 * side does not append a null byte to the buffer.
477 */
478 buf[r] = '\0';
479 return buf;
480 }
481#else
482 return NULL;
483#endif
484}
485
Roland McGrath9814a942005-07-04 23:28:10 +0000486void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300487printfd(struct tcb *tcp, int fd)
488{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100489 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000490 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
491 static const char socket_prefix[] = "socket:[";
492 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
493 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000494
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000495 if (show_fd_path > 1 &&
496 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
497 path[(path_len = strlen(path)) - 1] == ']') {
498 unsigned long inodenr;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900499#define PROTO_NAME_LEN 32
500 char proto_buf[PROTO_NAME_LEN];
501 const char *proto =
502 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000503 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
504 tprintf("%d<", fd);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900505 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900506 if (proto)
507 tprintf("%s:[%lu]", proto, inodenr);
508 else
509 tprints(path);
510 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000511 tprints(">");
512 } else {
513 tprintf("%d<%s>", fd, path);
514 }
515 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000516 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300517}
518
Dmitry V. Levina501f142008-11-10 23:19:13 +0000519/*
520 * Quote string `instr' of length `size'
521 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200522 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000523 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100524 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200525 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100526 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000527 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400528int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200529string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000531 const unsigned char *ustr = (const unsigned char *) instr;
532 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200533 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200535 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200536 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200537 size--;
538 eol = '\0';
539 }
540
541 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000542 if (xflag > 1)
543 usehex = 1;
544 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000545 /* Check for presence of symbol which require
546 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000547 for (i = 0; i < size; ++i) {
548 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000549 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200550 if (c == eol)
551 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100552
553 /* Force hex unless c is printable or whitespace */
554 if (c > 0x7e) {
555 usehex = 1;
556 break;
557 }
558 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
559 * They happen to have ASCII codes 9,10,11,12,13.
560 */
561 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000562 usehex = 1;
563 break;
564 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000565 }
566 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567
568 *s++ = '\"';
569
570 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000571 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000572 for (i = 0; i < size; ++i) {
573 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000574 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200575 if (c == eol)
576 goto asciz_ended;
577 *s++ = '\\';
578 *s++ = 'x';
579 *s++ = "0123456789abcdef"[c >> 4];
580 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000581 }
582 } else {
583 for (i = 0; i < size; ++i) {
584 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000585 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200586 if (c == eol)
587 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000588 switch (c) {
589 case '\"': case '\\':
590 *s++ = '\\';
591 *s++ = c;
592 break;
593 case '\f':
594 *s++ = '\\';
595 *s++ = 'f';
596 break;
597 case '\n':
598 *s++ = '\\';
599 *s++ = 'n';
600 break;
601 case '\r':
602 *s++ = '\\';
603 *s++ = 'r';
604 break;
605 case '\t':
606 *s++ = '\\';
607 *s++ = 't';
608 break;
609 case '\v':
610 *s++ = '\\';
611 *s++ = 'v';
612 break;
613 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100614 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000615 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200616 else {
617 /* Print \octal */
618 *s++ = '\\';
619 if (i + 1 < size
620 && ustr[i + 1] >= '0'
621 && ustr[i + 1] <= '9'
622 ) {
623 /* Print \ooo */
624 *s++ = '0' + (c >> 6);
625 *s++ = '0' + ((c >> 3) & 0x7);
626 } else {
627 /* Print \[[o]o]o */
628 if ((c >> 3) != 0) {
629 if ((c >> 6) != 0)
630 *s++ = '0' + (c >> 6);
631 *s++ = '0' + ((c >> 3) & 0x7);
632 }
633 }
634 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000635 }
636 break;
637 }
638 }
639 }
640
641 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000642 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000643
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200644 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200645 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200646 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
647 * but next char is NUL.
648 */
649 return 0;
650 }
651
652 return 1;
653
654 asciz_ended:
655 *s++ = '\"';
656 *s = '\0';
657 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
658 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000659}
660
Dmitry V. Levina501f142008-11-10 23:19:13 +0000661/*
662 * Print path string specified by address `addr' and length `n'.
663 * If path length exceeds `n', append `...' to the output.
664 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000666printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000668 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100669 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100670
Dmitry V. Levina501f142008-11-10 23:19:13 +0000671 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200672 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000673 return;
674 }
675
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100676 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000677 if (n > sizeof path - 1)
678 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000679
680 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100681 nul_seen = umovestr(tcp, addr, n + 1, path);
682 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683 tprintf("%#lx", addr);
684 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100685 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000686
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100687 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100688 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100689 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100690 string_quote(path, outstr, -1, n);
691 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100692 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100693 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 }
695}
696
697void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000698printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100700 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000701 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000702}
703
Dmitry V. Levina501f142008-11-10 23:19:13 +0000704/*
705 * Print string specified by address `addr' and length `len'.
706 * If `len' < 0, treat the string as a NUL-terminated string.
707 * If string length exceeds `max_strlen', append `...' to the output.
708 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000709void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200710printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000711{
712 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000714 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100715 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716
717 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200718 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 return;
720 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000721 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200722 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000723 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
724
725 if (outstr_size / 4 != max_strlen)
726 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000727 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200728 if (!str)
729 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000730 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200731 if (!outstr)
732 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000734
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200735 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000736 /*
737 * Treat as a NUL-terminated string: fetch one byte more
738 * because string_quote() quotes one byte less.
739 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000740 size = max_strlen + 1;
741 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 tprintf("%#lx", addr);
743 return;
744 }
745 }
746 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200747 size = max_strlen;
748 if (size > (unsigned long)len)
749 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000750 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 tprintf("%#lx", addr);
752 return;
753 }
754 }
755
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100756 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
757 * or we were requested to print more than -s NUM chars)...
758 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100759 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000760 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000761
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100762 tprints(outstr);
763 if (ellipsis)
764 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765}
766
John Hughes1d08dcf2001-07-10 13:48:44 +0000767void
Denys Vlasenko12014262011-05-30 14:00:14 +0200768dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000769{
Denys Vlasenko84703742012-02-25 02:38:52 +0100770#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000771 union {
772 struct { u_int32_t base; u_int32_t len; } *iov32;
773 struct { u_int64_t base; u_int64_t len; } *iov64;
774 } iovu;
775#define iov iovu.iov64
776#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100777 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000778#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100779 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000780#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100781 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000782#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000783 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000784#define sizeof_iov sizeof(*iov)
785#define iov_iov_base(i) iov[i].iov_base
786#define iov_iov_len(i) iov[i].iov_len
787#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000788 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200789 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000790
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200791 size = sizeof_iov * len;
792 /* Assuming no sane program has millions of iovs */
793 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000794 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200795 fprintf(stderr, "Out of memory\n");
796 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000797 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000798 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000799 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000800 /* include the buffer number to make it easy to
801 * match up the trace with the source */
802 tprintf(" * %lu bytes in buffer %d\n",
803 (unsigned long)iov_iov_len(i), i);
804 dumpstr(tcp, (long) iov_iov_base(i),
805 iov_iov_len(i));
806 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000807 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200808 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000809#undef sizeof_iov
810#undef iov_iov_base
811#undef iov_iov_len
812#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000813}
John Hughes1d08dcf2001-07-10 13:48:44 +0000814
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815void
Denys Vlasenko12014262011-05-30 14:00:14 +0200816dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817{
818 static int strsize = -1;
819 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820
Denys Vlasenko76325802013-02-22 14:47:39 +0100821 char outbuf[
822 (
823 (sizeof(
824 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
825 "1234567890123456") + /*in case I'm off by few:*/ 4)
826 /*align to 8 to make memset easier:*/ + 7) & -8
827 ];
828 const unsigned char *src;
829 int i;
830
831 memset(outbuf, ' ', sizeof(outbuf));
832
833 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200834 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100835 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200836 if (!str) {
837 strsize = -1;
838 fprintf(stderr, "Out of memory\n");
839 return;
840 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100841 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000842 }
843
844 if (umoven(tcp, addr, len, (char *) str) < 0)
845 return;
846
Denys Vlasenko76325802013-02-22 14:47:39 +0100847 /* Space-pad to 16 bytes */
848 i = len;
849 while (i & 0xf)
850 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200851
Denys Vlasenko76325802013-02-22 14:47:39 +0100852 i = 0;
853 src = str;
854 while (i < len) {
855 char *dst = outbuf;
856 /* Hex dump */
857 do {
858 if (i < len) {
859 *dst++ = "0123456789abcdef"[*src >> 4];
860 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000861 }
862 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100863 *dst++ = ' ';
864 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000865 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100866 dst++; /* space is there by memset */
867 i++;
868 if ((i & 7) == 0)
869 dst++; /* space is there by memset */
870 src++;
871 } while (i & 0xf);
872 /* ASCII dump */
873 i -= 16;
874 src -= 16;
875 do {
876 if (*src >= ' ' && *src < 0x7f)
877 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100879 *dst++ = '.';
880 src++;
881 } while (++i & 0xf);
882 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100883 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884 }
885}
886
Mike Frysinger612659e2012-02-14 14:38:28 +0100887#ifdef HAVE_PROCESS_VM_READV
888/* C library supports this, but the kernel might not. */
889static bool process_vm_readv_not_supported = 0;
890#else
891
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100892/* Need to do this since process_vm_readv() is not yet available in libc.
893 * When libc is be updated, only "static bool process_vm_readv_not_supported"
894 * line should remain.
895 */
896#if !defined(__NR_process_vm_readv)
897# if defined(I386)
898# define __NR_process_vm_readv 347
899# elif defined(X86_64)
900# define __NR_process_vm_readv 310
901# elif defined(POWERPC)
902# define __NR_process_vm_readv 351
903# endif
904#endif
905
906#if defined(__NR_process_vm_readv)
907static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400908/* Have to avoid duplicating with the C library headers. */
909static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100910 const struct iovec *lvec,
911 unsigned long liovcnt,
912 const struct iovec *rvec,
913 unsigned long riovcnt,
914 unsigned long flags)
915{
916 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
917}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400918#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100919#else
920static bool process_vm_readv_not_supported = 1;
921# define process_vm_readv(...) (errno = ENOSYS, -1)
922#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100923
924#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100925
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926#define PAGMASK (~(PAGSIZ - 1))
927/*
928 * move `len' bytes of data from process `pid'
929 * at address `addr' to our space at `laddr'
930 */
931int
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000932umoven(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700934 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000935 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936 union {
937 long val;
938 char x[sizeof(long)];
939 } u;
940
Denys Vlasenko2544f982013-02-19 17:39:56 +0100941#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100942 if (current_wordsize < sizeof(addr))
943 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100944#endif
945
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100946 if (!process_vm_readv_not_supported) {
947 struct iovec local[1], remote[1];
948 int r;
949
950 local[0].iov_base = laddr;
951 remote[0].iov_base = (void*)addr;
952 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000953 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000954 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100955 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000956 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000957 error_msg("umoven: short read (%u < %u) @0x%lx",
958 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000959 return -1;
960 }
961 switch (errno) {
962 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100963 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000964 break;
965 case ESRCH:
966 /* the process is gone */
967 return -1;
968 case EFAULT: case EIO: case EPERM:
969 /* address space is inaccessible */
970 return -1;
971 default:
972 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100973 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000974 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100975 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100976 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100977
Dmitry V. Levin97005922013-02-26 21:16:22 +0000978 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 if (addr & (sizeof(long) - 1)) {
980 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000981 n = addr & (sizeof(long) - 1); /* residue */
982 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700983 errno = 0;
984 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000985 switch (errno) {
986 case 0:
987 break;
988 case ESRCH: case EINVAL:
989 /* these could be seen if the process is gone */
990 return -1;
991 case EFAULT: case EIO: case EPERM:
992 /* address space is inaccessible */
993 return -1;
994 default:
995 /* all the rest is strange and should be reported */
996 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
997 pid, addr);
998 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700999 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001000 m = MIN(sizeof(long) - n, len);
1001 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001002 addr += sizeof(long);
1003 laddr += m;
1004 nread += m;
1005 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 }
1007 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001008 errno = 0;
1009 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001010 switch (errno) {
1011 case 0:
1012 break;
1013 case ESRCH: case EINVAL:
1014 /* these could be seen if the process is gone */
1015 return -1;
1016 case EFAULT: case EIO: case EPERM:
1017 /* address space is inaccessible */
1018 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001019 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001020 nread, nread + len, addr - nread);
1021 }
1022 return -1;
1023 default:
1024 /* all the rest is strange and should be reported */
1025 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1026 pid, addr);
1027 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001028 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001029 m = MIN(sizeof(long), len);
1030 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001031 addr += sizeof(long);
1032 laddr += m;
1033 nread += m;
1034 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 return 0;
1038}
1039
1040/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001041 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001043 *
1044 * Returns < 0 on error, > 0 if NUL was seen,
1045 * (TODO if useful: return count of bytes including NUL),
1046 * else 0 if len bytes were read but no NUL byte seen.
1047 *
1048 * Note: there is no guarantee we won't overwrite some bytes
1049 * in laddr[] _after_ terminating NUL (but, of course,
1050 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 */
1052int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001053umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054{
Denys Vlasenko16940922013-03-01 18:52:59 +01001055#if SIZEOF_LONG == 4
1056 const unsigned long x01010101 = 0x01010101ul;
1057 const unsigned long x80808080 = 0x80808080ul;
1058#elif SIZEOF_LONG == 8
1059 const unsigned long x01010101 = 0x0101010101010101ul;
1060 const unsigned long x80808080 = 0x8080808080808080ul;
1061#else
1062# error SIZEOF_LONG > 8
1063#endif
1064
Roland McGratheb9e2e82009-06-02 16:49:22 -07001065 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001066 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001067 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001068 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 char x[sizeof(long)];
1070 } u;
1071
Denys Vlasenko2544f982013-02-19 17:39:56 +01001072#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001073 if (current_wordsize < sizeof(addr))
1074 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001075#endif
1076
Dmitry V. Levin97005922013-02-26 21:16:22 +00001077 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001078 if (!process_vm_readv_not_supported) {
1079 struct iovec local[1], remote[1];
1080
1081 local[0].iov_base = laddr;
1082 remote[0].iov_base = (void*)addr;
1083
1084 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001085 unsigned int chunk_len;
1086 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001087 int r;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001088
1089 /* Don't read kilobytes: most strings are short */
1090 chunk_len = len;
1091 if (chunk_len > 256)
1092 chunk_len = 256;
1093 /* Don't cross pages. I guess otherwise we can get EFAULT
1094 * and fail to notice that terminating NUL lies
1095 * in the existing (first) page.
1096 * (I hope there aren't arches with pages < 4K)
1097 */
1098 end_in_page = ((addr + chunk_len) & 4095);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001099 if (chunk_len > end_in_page) /* crosses to the next page */
1100 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001101
1102 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001103 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1104 if (r > 0) {
1105 if (memchr(local[0].iov_base, '\0', r))
1106 return 1;
1107 local[0].iov_base += r;
1108 remote[0].iov_base += r;
1109 len -= r;
1110 nread += r;
1111 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001112 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001113 switch (errno) {
1114 case ENOSYS:
1115 process_vm_readv_not_supported = 1;
1116 goto vm_readv_didnt_work;
1117 case ESRCH:
1118 /* the process is gone */
1119 return -1;
1120 case EFAULT: case EIO: case EPERM:
1121 /* address space is inaccessible */
1122 if (nread) {
1123 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1124 nread, nread + len, addr);
1125 }
1126 return -1;
1127 default:
1128 /* all the rest is strange and should be reported */
1129 perror_msg("process_vm_readv");
1130 return -1;
1131 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001132 }
1133 return 0;
1134 }
1135 vm_readv_didnt_work:
1136
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 if (addr & (sizeof(long) - 1)) {
1138 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001139 n = addr & (sizeof(long) - 1); /* residue */
1140 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001141 errno = 0;
1142 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001143 switch (errno) {
1144 case 0:
1145 break;
1146 case ESRCH: case EINVAL:
1147 /* these could be seen if the process is gone */
1148 return -1;
1149 case EFAULT: case EIO: case EPERM:
1150 /* address space is inaccessible */
1151 return -1;
1152 default:
1153 /* all the rest is strange and should be reported */
1154 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1155 pid, addr);
1156 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001157 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001158 m = MIN(sizeof(long) - n, len);
1159 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160 while (n & (sizeof(long) - 1))
1161 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001162 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001163 addr += sizeof(long);
1164 laddr += m;
1165 nread += m;
1166 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001168
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001170 errno = 0;
1171 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001172 switch (errno) {
1173 case 0:
1174 break;
1175 case ESRCH: case EINVAL:
1176 /* these could be seen if the process is gone */
1177 return -1;
1178 case EFAULT: case EIO: case EPERM:
1179 /* address space is inaccessible */
1180 if (nread) {
1181 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1182 nread, nread + len, addr - nread);
1183 }
1184 return -1;
1185 default:
1186 /* all the rest is strange and should be reported */
1187 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1188 pid, addr);
1189 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001190 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001191 m = MIN(sizeof(long), len);
1192 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001193 /* "If a NUL char exists in this word" */
1194 if ((u.val - x01010101) & ~u.val & x80808080)
1195 return 1;
1196 addr += sizeof(long);
1197 laddr += m;
1198 nread += m;
1199 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001201 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202}
1203
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001205upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206{
1207 long val;
1208
Roland McGratheb9e2e82009-06-02 16:49:22 -07001209 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001210 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001211 if (val == -1 && errno) {
1212 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001213 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001214 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001216 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 *res = val;
1218 return 0;
1219}
1220
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001221/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1222 * and PTRACE_O_TRACE[V]FORK for tracing children.
1223 * If you are adding a new arch which is only supported by newer kernels,
1224 * you most likely don't need to add any code below
1225 * beside a dummy "return 0" block in change_syscall().
1226 */
1227
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001228/*
1229 * These #if's are huge, please indent them correctly.
1230 * It's easy to get confused otherwise.
1231 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001233#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001234
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001235#ifndef CLONE_PTRACE
1236# define CLONE_PTRACE 0x00002000
1237#endif
1238#ifndef CLONE_VFORK
1239# define CLONE_VFORK 0x00004000
1240#endif
1241#ifndef CLONE_VM
1242# define CLONE_VM 0x00000100
1243#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001244
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001245#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001246
1247typedef unsigned long *arg_setup_state;
1248
1249static int
1250arg_setup(struct tcb *tcp, arg_setup_state *state)
1251{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001252 unsigned long cfm, sof, sol;
1253 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001255 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001256 /* Satisfy a false GCC warning. */
1257 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001258 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001259 }
Roland McGrath08267b82004-02-20 22:56:43 +00001260
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001261 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001263 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001264 return -1;
1265
1266 sof = (cfm >> 0) & 0x7f;
1267 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001268 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269
Jan Kratochvil1f942712008-08-06 21:38:52 +00001270 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271 return 0;
1272}
1273
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001274# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275
Roland McGrathd81f1d92003-01-09 06:53:34 +00001276static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001277get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001278{
Roland McGrath08267b82004-02-20 22:56:43 +00001279 int ret;
1280
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001281 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001282 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001283 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001284 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001285 (unsigned long) ia64_rse_skip_regs(*state, 0),
1286 sizeof(long), (void *) valp);
1287 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001288}
1289
1290static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001291get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292{
Roland McGrath08267b82004-02-20 22:56:43 +00001293 int ret;
1294
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001295 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001296 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001297 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001298 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001299 (unsigned long) ia64_rse_skip_regs(*state, 1),
1300 sizeof(long), (void *) valp);
1301 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001302}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303
1304static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001305set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001306{
Roland McGrath08267b82004-02-20 22:56:43 +00001307 int req = PTRACE_POKEDATA;
1308 void *ap;
1309
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001310 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001311 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1312 req = PTRACE_POKEUSER;
1313 } else
1314 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001315 errno = 0;
1316 ptrace(req, tcp->pid, ap, val);
1317 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318}
1319
1320static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001321set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001322{
Roland McGrath08267b82004-02-20 22:56:43 +00001323 int req = PTRACE_POKEDATA;
1324 void *ap;
1325
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001326 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001327 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1328 req = PTRACE_POKEUSER;
1329 } else
1330 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001331 errno = 0;
1332 ptrace(req, tcp->pid, ap, val);
1333 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001334}
1335
Roland McGrathb659f872008-07-18 01:19:36 +00001336/* ia64 does not return the input arguments from functions (and syscalls)
1337 according to ia64 RSE (Register Stack Engine) behavior. */
1338
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001339# define restore_arg0(tcp, state, val) ((void) (state), 0)
1340# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001341
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001342#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001343
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001344# if defined(SPARC64)
1345# undef PTRACE_GETREGS
1346# define PTRACE_GETREGS PTRACE_GETREGS64
1347# undef PTRACE_SETREGS
1348# define PTRACE_SETREGS PTRACE_SETREGS64
1349# endif
1350
Mike Frysinger8566c502009-10-12 11:05:14 -04001351typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001353# define arg_setup(tcp, state) \
1354 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1355# define arg_finish_change(tcp, state) \
1356 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001358# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1359# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1360# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1361# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1362# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001363
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001364#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001366# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001367/* Note: this is only true for the `clone' system call, which handles
1368 arguments specially. We could as well say that its first two arguments
1369 are swapped relative to other architectures, but that would just be
1370 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001371# define arg0_offset PT_GPR3
1372# define arg1_offset PT_ORIGGPR2
1373# define restore_arg0(tcp, state, val) ((void) (state), 0)
1374# define restore_arg1(tcp, state, val) ((void) (state), 0)
1375# define arg0_index 1
1376# define arg1_index 0
1377# elif defined(ALPHA) || defined(MIPS)
1378# define arg0_offset REG_A0
1379# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001380# elif defined(POWERPC)
1381# define arg0_offset (sizeof(unsigned long)*PT_R3)
1382# define arg1_offset (sizeof(unsigned long)*PT_R4)
1383# define restore_arg0(tcp, state, val) ((void) (state), 0)
1384# elif defined(HPPA)
1385# define arg0_offset PT_GR26
1386# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001387# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001388# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1389# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1390# elif defined(SH)
1391# define arg0_offset (4*(REG_REG0+4))
1392# define arg1_offset (4*(REG_REG0+5))
1393# elif defined(SH64)
1394 /* ABI defines arg0 & 1 in r2 & r3 */
1395# define arg0_offset (REG_OFFSET+16)
1396# define arg1_offset (REG_OFFSET+24)
1397# define restore_arg0(tcp, state, val) 0
1398# elif defined CRISV10 || defined CRISV32
1399# define arg0_offset (4*PT_R11)
1400# define arg1_offset (4*PT_ORIG_R10)
1401# define restore_arg0(tcp, state, val) 0
1402# define restore_arg1(tcp, state, val) 0
1403# define arg0_index 1
1404# define arg1_index 0
1405# else
1406# define arg0_offset 0
1407# define arg1_offset 4
1408# if defined ARM
1409# define restore_arg0(tcp, state, val) 0
1410# endif
1411# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412
1413typedef int arg_setup_state;
1414
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001415# define arg_setup(tcp, state) (0)
1416# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001417# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1418# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001419
1420static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001421set_arg0(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*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001424}
1425
1426static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001427set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001428{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001430}
1431
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001432#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001433
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001434#ifndef restore_arg0
1435# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1436#endif
1437#ifndef restore_arg1
1438# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1439#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001440
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001441#ifndef arg0_index
1442# define arg0_index 0
1443# define arg1_index 1
1444#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001445
James Hogan05eb9052012-11-29 17:37:37 +00001446static int
1447change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1448{
1449#if defined(I386)
1450 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1451 return -1;
1452 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001453#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001454 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1455 return -1;
1456 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001457#elif defined(X32)
1458 /* setbpt/clearbpt never used: */
1459 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001460#elif defined(POWERPC)
1461 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1462 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1463 return -1;
1464 return 0;
1465#elif defined(S390) || defined(S390X)
1466 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1467 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1468 return -1;
1469 return 0;
1470#elif defined(M68K)
1471 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1472 return -1;
1473 return 0;
1474#elif defined(SPARC) || defined(SPARC64)
1475 state->u_regs[U_REG_G1] = new;
1476 return 0;
1477#elif defined(MIPS)
1478 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1479 return -1;
1480 return 0;
1481#elif defined(ALPHA)
1482 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1483 return -1;
1484 return 0;
1485#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001486 /* setbpt/clearbpt never used: */
1487 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001488#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001489 /* setbpt/clearbpt never used: */
1490 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001491#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001492 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001493 switch (new) {
1494 case 2:
1495 break; /* x86 SYS_fork */
1496 case SYS_clone:
1497 new = 120;
1498 break;
1499 default:
1500 fprintf(stderr, "%s: unexpected syscall %d\n",
1501 __FUNCTION__, new);
1502 return -1;
1503 }
1504 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1505 return -1;
1506 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1507 return -1;
1508 return 0;
1509#elif defined(HPPA)
1510 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1511 return -1;
1512 return 0;
1513#elif defined(SH)
1514 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1515 return -1;
1516 return 0;
1517#elif defined(SH64)
1518 /* Top half of reg encodes the no. of args n as 0x1n.
1519 Assume 0 args as kernel never actually checks... */
1520 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1521 0x100000 | new) < 0)
1522 return -1;
1523 return 0;
1524#elif defined(CRISV10) || defined(CRISV32)
1525 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1526 return -1;
1527 return 0;
1528#elif defined(ARM)
1529 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1530# ifndef PTRACE_SET_SYSCALL
1531# define PTRACE_SET_SYSCALL 23
1532# endif
1533 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1534 return -1;
1535 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001536#elif defined(AARCH64)
1537 /* setbpt/clearbpt never used: */
1538 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001539#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001540 /* setbpt/clearbpt never used: */
1541 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001542#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001543 /* setbpt/clearbpt never used: */
1544 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001545#elif defined(OR1K)
1546 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001547#elif defined(METAG)
1548 /* setbpt/clearbpt never used: */
1549 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001550#elif defined(XTENSA)
1551 /* setbpt/clearbpt never used: */
1552 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301553#elif defined(ARC)
1554 /* setbpt/clearbpt never used: */
1555 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001556#else
1557#warning Do not know how to handle change_syscall for this architecture
1558#endif /* architecture */
1559 return -1;
1560}
1561
Roland McGrathd81f1d92003-01-09 06:53:34 +00001562int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001563setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001564{
Roland McGrath3291ef22008-05-20 00:34:34 +00001565 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001566 arg_setup_state state;
1567
1568 if (tcp->flags & TCB_BPTSET) {
1569 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1570 return -1;
1571 }
1572
Roland McGrath3291ef22008-05-20 00:34:34 +00001573 /*
1574 * It's a silly kludge to initialize this with a search at runtime.
1575 * But it's better than maintaining another magic thing in the
1576 * godforsaken tables.
1577 */
1578 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001579 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001580 for (i = 0; i < nsyscalls; ++i)
1581 if (sysent[i].sys_func == sys_clone) {
1582 clone_scno[current_personality] = i;
1583 break;
1584 }
1585 }
1586
Dmitry V. Levin65563152014-05-12 13:43:10 +00001587 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001588 if (arg_setup(tcp, &state) < 0
1589 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1590 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001591 || change_syscall(tcp, &state,
1592 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001593 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1594 || set_arg1(tcp, &state, 0) < 0
1595 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001596 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001597 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1598 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001599 tcp->flags |= TCB_BPTSET;
1600 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001601 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001602
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001603 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001604 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001605 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001606 vfork semantics into plain fork - each application must not
1607 depend on the vfork specifics according to POSIX. We would
1608 hang waiting for the parent resume otherwise. We need to
1609 clear also CLONE_VM but only in the CLONE_VFORK case as
1610 otherwise we would break pthread_create. */
1611
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001612 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1613 if (new_arg0 & CLONE_VFORK)
1614 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1615 if (arg_setup(tcp, &state) < 0
1616 || set_arg0(tcp, &state, new_arg0) < 0
1617 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001618 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001619 tcp->inst[0] = tcp->u_arg[arg0_index];
1620 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001621 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001622 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001623 }
1624
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001625 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1626 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001627 return -1;
1628}
1629
1630int
Denys Vlasenko12014262011-05-30 14:00:14 +02001631clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001632{
1633 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001634 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001635 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001636 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1637 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1638 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001639 if (errno != ESRCH)
1640 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001641 tcp->flags &= ~TCB_BPTSET;
1642 return 0;
1643}