blob: f10c011cefb5a97e1fc3e6388e407923261afbbf [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
36#include <sys/param.h>
37#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000038#if HAVE_SYS_UIO_H
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010039# include <sys/uio.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000040#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000041
Denys Vlasenko84703742012-02-25 02:38:52 +010042#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000043# include <asm/ptrace_offsets.h>
44# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000045#endif
46
Wichert Akkerman36915a11999-07-13 15:45:02 +000047#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010048# include <sys/reg.h>
Wichert Akkermanfaf72222000-02-19 23:59:03 +000049#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010050# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000051# ifdef HAVE_STRUCT_IA64_FPREG
52# define ia64_fpreg XXX_ia64_fpreg
53# endif
54# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
55# define pt_all_user_regs XXX_pt_all_user_regs
56# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030057# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
58# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
59# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010060# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030061# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000062# undef ia64_fpreg
63# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000064#endif
65
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000066int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000067string_to_uint(const char *str)
68{
69 char *error;
70 long value;
71
72 if (!*str)
73 return -1;
74 errno = 0;
75 value = strtol(str, &error, 10);
76 if (errno || *error || value < 0 || (long)(int)value != value)
77 return -1;
78 return (int)value;
79}
80
81int
Dmitry V. Levin447db452014-05-29 17:59:01 +000082tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083{
84 return a->tv_sec || a->tv_usec;
85}
86
87int
Dmitry V. Levin447db452014-05-29 17:59:01 +000088tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089{
90 if (a->tv_sec < b->tv_sec
91 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
92 return -1;
93 if (a->tv_sec > b->tv_sec
94 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
95 return 1;
96 return 0;
97}
98
99double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000100tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101{
102 return tv->tv_sec + tv->tv_usec/1000000.0;
103}
104
105void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000106tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107{
108 tv->tv_sec = a->tv_sec + b->tv_sec;
109 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000110 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111 tv->tv_sec++;
112 tv->tv_usec -= 1000000;
113 }
114}
115
116void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000117tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118{
119 tv->tv_sec = a->tv_sec - b->tv_sec;
120 tv->tv_usec = a->tv_usec - b->tv_usec;
121 if (((long) tv->tv_usec) < 0) {
122 tv->tv_sec--;
123 tv->tv_usec += 1000000;
124 }
125}
126
127void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000128tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129{
130 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
131 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
132 tv->tv_usec %= 1000000;
133}
134
135void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000136tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137{
138 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000139 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140 tv->tv_usec %= 1000000;
141}
142
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000143const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000144xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145{
146 for (; xlat->str != NULL; xlat++)
147 if (xlat->val == val)
148 return xlat->str;
149 return NULL;
150}
151
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200152#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200153char *
154stpcpy(char *dst, const char *src)
155{
156 while ((*dst = *src++) != '\0')
157 dst++;
158 return dst;
159}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200160#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200161
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100162/* Find a next bit which is set.
163 * Starts testing at cur_bit.
164 * Returns -1 if no more bits are set.
165 *
166 * We never touch bytes we don't need to.
167 * On big-endian, array is assumed to consist of
168 * current_wordsize wide words: for example, is current_wordsize is 4,
169 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
170 * On little-endian machines, word size is immaterial.
171 */
172int
173next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
174{
175 const unsigned endian = 1;
176 int little_endian = *(char*)&endian;
177
178 const uint8_t *array = bit_array;
179 unsigned pos = cur_bit / 8;
180 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
181
182 for (;;) {
183 uint8_t bitmask;
184 uint8_t cur_byte;
185
186 if (cur_bit >= size_bits)
187 return -1;
188 cur_byte = array[pos ^ pos_xor_mask];
189 if (cur_byte == 0) {
190 cur_bit = (cur_bit + 8) & (-8);
191 pos++;
192 continue;
193 }
194 bitmask = 1 << (cur_bit & 7);
195 for (;;) {
196 if (cur_byte & bitmask)
197 return cur_bit;
198 cur_bit++;
199 if (cur_bit >= size_bits)
200 return -1;
201 bitmask <<= 1;
202 /* This check *can't be* optimized out: */
203 if (bitmask == 0)
204 break;
205 }
206 pos++;
207 }
208}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209/*
210 * Print entry in struct xlat table, if there.
211 */
212void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000213printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000215 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000216
217 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200218 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000219 else
220 tprintf("%#x /* %s */", val, dflt);
221}
222
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100223/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100224 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100225 * argument.
226 */
227int
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000228printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100229{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000230#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
231# if SUPPORTED_PERSONALITIES > 1
232 if (current_wordsize > 4) {
233# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100234 tprintf(format, tcp->u_arg[arg_no]);
235 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000236# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100237 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000238# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000239 /* Align arg_no to the next even number. */
240 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000241# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100242 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
243 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100244 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000245# endif /* SUPPORTED_PERSONALITIES */
246#elif SIZEOF_LONG > 4
247# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
248#elif defined LINUX_MIPSN32
249 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100250 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000251#elif defined X32
252 if (current_personality == 0) {
253 tprintf(format, tcp->ext_arg[arg_no]);
254 arg_no++;
255 } else {
256 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
257 arg_no += 2;
258 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100259#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000260# if defined __ARM_EABI__ || \
261 defined LINUX_MIPSO32 || \
262 defined POWERPC || \
263 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000264 /* Align arg_no to the next even number. */
265 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000266# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100267 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
268 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100269#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000270
Chris Metcalf879dddd2013-03-01 10:41:02 +0100271 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100272}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100273
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000274/*
275 * Interpret `xlat' as an array of flags
276 * print the entries whose bits are on in `flags'
277 * return # of flags printed.
278 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200279void
Denys Vlasenko12014262011-05-30 14:00:14 +0200280addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200282 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000283 if (xlat->val && (flags & xlat->val) == xlat->val) {
284 tprintf("|%s", xlat->str);
285 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286 }
287 }
288 if (flags) {
289 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291}
292
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000293/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200294 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000295 * Print to static string the entries whose bits are on in `flags'
296 * Return static string.
297 */
298const char *
299sprintflags(const char *prefix, const struct xlat *xlat, int flags)
300{
301 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200302 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000303 int found = 0;
304
Denys Vlasenko52845572011-08-31 12:07:38 +0200305 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000306
307 for (; xlat->str; xlat++) {
308 if ((flags & xlat->val) == xlat->val) {
309 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200310 *outptr++ = '|';
311 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000312 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100313 flags &= ~xlat->val;
314 if (!flags)
315 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000316 }
317 }
318 if (flags) {
319 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200320 *outptr++ = '|';
321 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000322 }
323
324 return outstr;
325}
326
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000328printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000329{
330 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000331 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000332
333 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200334 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000335 return 1;
336 }
337
338 sep = "";
339 for (n = 0; xlat->str; xlat++) {
340 if (xlat->val && (flags & xlat->val) == xlat->val) {
341 tprintf("%s%s", sep, xlat->str);
342 flags &= ~xlat->val;
343 sep = "|";
344 n++;
345 }
346 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000347
348 if (n) {
349 if (flags) {
350 tprintf("%s%#x", sep, flags);
351 n++;
352 }
353 } else {
354 if (flags) {
355 tprintf("%#x", flags);
356 if (dflt)
357 tprintf(" /* %s */", dflt);
358 } else {
359 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200360 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000361 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000362 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000363
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364 return n;
365}
366
367void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000368printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000369{
Roland McGratheb285352003-01-14 09:59:00 +0000370 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000371
372 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200373 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000374 return;
375 }
376 if (umove(tcp, addr, &num) < 0) {
377 tprintf("%#lx", addr);
378 return;
379 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200380 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200382 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383}
384
Roland McGrath6bc12202003-11-13 22:32:27 +0000385void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000386printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000387{
388 int num;
389
390 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200391 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000392 return;
393 }
394 if (umove(tcp, addr, &num) < 0) {
395 tprintf("%#lx", addr);
396 return;
397 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200398 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000399 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200400 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000401}
402
403void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300404printfd(struct tcb *tcp, int fd)
405{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100406 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000407 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
408 static const char socket_prefix[] = "socket:[";
409 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
410 size_t path_len;
Grant Edwards8a082772011-04-07 20:25:40 +0000411
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000412 if (show_fd_path > 1 &&
413 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
414 path[(path_len = strlen(path)) - 1] == ']') {
415 unsigned long inodenr;
416 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
417 tprintf("%d<", fd);
418 if (!print_sockaddr_by_inode(inodenr))
419 tprints(path);
420 tprints(">");
421 } else {
422 tprintf("%d<%s>", fd, path);
423 }
424 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000425 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300426}
427
428void
Denys Vlasenko12014262011-05-30 14:00:14 +0200429printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000430{
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000431 tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000432}
433
Dmitry V. Levina501f142008-11-10 23:19:13 +0000434/*
435 * Quote string `instr' of length `size'
436 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200437 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000438 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100439 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200440 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100441 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000442 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400443int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200444string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000445{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000446 const unsigned char *ustr = (const unsigned char *) instr;
447 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200448 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000449
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200450 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200451 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200452 size--;
453 eol = '\0';
454 }
455
456 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000457 if (xflag > 1)
458 usehex = 1;
459 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000460 /* Check for presence of symbol which require
461 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000462 for (i = 0; i < size; ++i) {
463 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000464 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200465 if (c == eol)
466 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100467
468 /* Force hex unless c is printable or whitespace */
469 if (c > 0x7e) {
470 usehex = 1;
471 break;
472 }
473 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
474 * They happen to have ASCII codes 9,10,11,12,13.
475 */
476 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000477 usehex = 1;
478 break;
479 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000480 }
481 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000482
483 *s++ = '\"';
484
485 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000486 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000487 for (i = 0; i < size; ++i) {
488 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000489 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200490 if (c == eol)
491 goto asciz_ended;
492 *s++ = '\\';
493 *s++ = 'x';
494 *s++ = "0123456789abcdef"[c >> 4];
495 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000496 }
497 } else {
498 for (i = 0; i < size; ++i) {
499 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000500 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200501 if (c == eol)
502 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000503 switch (c) {
504 case '\"': case '\\':
505 *s++ = '\\';
506 *s++ = c;
507 break;
508 case '\f':
509 *s++ = '\\';
510 *s++ = 'f';
511 break;
512 case '\n':
513 *s++ = '\\';
514 *s++ = 'n';
515 break;
516 case '\r':
517 *s++ = '\\';
518 *s++ = 'r';
519 break;
520 case '\t':
521 *s++ = '\\';
522 *s++ = 't';
523 break;
524 case '\v':
525 *s++ = '\\';
526 *s++ = 'v';
527 break;
528 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100529 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000530 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200531 else {
532 /* Print \octal */
533 *s++ = '\\';
534 if (i + 1 < size
535 && ustr[i + 1] >= '0'
536 && ustr[i + 1] <= '9'
537 ) {
538 /* Print \ooo */
539 *s++ = '0' + (c >> 6);
540 *s++ = '0' + ((c >> 3) & 0x7);
541 } else {
542 /* Print \[[o]o]o */
543 if ((c >> 3) != 0) {
544 if ((c >> 6) != 0)
545 *s++ = '0' + (c >> 6);
546 *s++ = '0' + ((c >> 3) & 0x7);
547 }
548 }
549 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550 }
551 break;
552 }
553 }
554 }
555
556 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000558
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200559 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200560 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200561 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
562 * but next char is NUL.
563 */
564 return 0;
565 }
566
567 return 1;
568
569 asciz_ended:
570 *s++ = '\"';
571 *s = '\0';
572 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
573 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574}
575
Dmitry V. Levina501f142008-11-10 23:19:13 +0000576/*
577 * Print path string specified by address `addr' and length `n'.
578 * If path length exceeds `n', append `...' to the output.
579 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000580void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000581printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000582{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100583 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100584 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100585
Dmitry V. Levina501f142008-11-10 23:19:13 +0000586 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200587 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000588 return;
589 }
590
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100591 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000592 if (n > sizeof path - 1)
593 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000594
595 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100596 nul_seen = umovestr(tcp, addr, n + 1, path);
597 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 tprintf("%#lx", addr);
599 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100600 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000601
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100602 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100603 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100604 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100605 string_quote(path, outstr, -1, n);
606 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100607 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100608 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000609 }
610}
611
612void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000613printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100615 /* Size must correspond to char path[] size in printpathn */
616 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000617}
618
Dmitry V. Levina501f142008-11-10 23:19:13 +0000619/*
620 * Print string specified by address `addr' and length `len'.
621 * If `len' < 0, treat the string as a NUL-terminated string.
622 * If string length exceeds `max_strlen', append `...' to the output.
623 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000624void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200625printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000626{
627 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000629 unsigned int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100630 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631
632 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200633 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000634 return;
635 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000636 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200637 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000638 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
639
640 if (outstr_size / 4 != max_strlen)
641 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000642 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200643 if (!str)
644 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000645 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200646 if (!outstr)
647 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000649
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200650 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000651 /*
652 * Treat as a NUL-terminated string: fetch one byte more
653 * because string_quote() quotes one byte less.
654 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000655 size = max_strlen + 1;
656 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657 tprintf("%#lx", addr);
658 return;
659 }
660 }
661 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200662 size = max_strlen;
663 if (size > (unsigned long)len)
664 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000665 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 tprintf("%#lx", addr);
667 return;
668 }
669 }
670
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100671 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
672 * or we were requested to print more than -s NUM chars)...
673 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100674 ellipsis = (string_quote(str, outstr, len, size) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000675 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000676
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100677 tprints(outstr);
678 if (ellipsis)
679 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680}
681
John Hughes1d08dcf2001-07-10 13:48:44 +0000682#if HAVE_SYS_UIO_H
683void
Denys Vlasenko12014262011-05-30 14:00:14 +0200684dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000685{
Denys Vlasenko84703742012-02-25 02:38:52 +0100686#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000687 union {
688 struct { u_int32_t base; u_int32_t len; } *iov32;
689 struct { u_int64_t base; u_int64_t len; } *iov64;
690 } iovu;
691#define iov iovu.iov64
692#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100693 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000694#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100695 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000696#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100697 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000698#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000699 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000700#define sizeof_iov sizeof(*iov)
701#define iov_iov_base(i) iov[i].iov_base
702#define iov_iov_len(i) iov[i].iov_len
703#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000704 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200705 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000706
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200707 size = sizeof_iov * len;
708 /* Assuming no sane program has millions of iovs */
709 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000710 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200711 fprintf(stderr, "Out of memory\n");
712 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000713 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000714 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000715 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000716 /* include the buffer number to make it easy to
717 * match up the trace with the source */
718 tprintf(" * %lu bytes in buffer %d\n",
719 (unsigned long)iov_iov_len(i), i);
720 dumpstr(tcp, (long) iov_iov_base(i),
721 iov_iov_len(i));
722 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000723 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200724 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000725#undef sizeof_iov
726#undef iov_iov_base
727#undef iov_iov_len
728#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000729}
730#endif
731
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732void
Denys Vlasenko12014262011-05-30 14:00:14 +0200733dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734{
735 static int strsize = -1;
736 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737
Denys Vlasenko76325802013-02-22 14:47:39 +0100738 char outbuf[
739 (
740 (sizeof(
741 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
742 "1234567890123456") + /*in case I'm off by few:*/ 4)
743 /*align to 8 to make memset easier:*/ + 7) & -8
744 ];
745 const unsigned char *src;
746 int i;
747
748 memset(outbuf, ' ', sizeof(outbuf));
749
750 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200751 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100752 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200753 if (!str) {
754 strsize = -1;
755 fprintf(stderr, "Out of memory\n");
756 return;
757 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100758 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759 }
760
761 if (umoven(tcp, addr, len, (char *) str) < 0)
762 return;
763
Denys Vlasenko76325802013-02-22 14:47:39 +0100764 /* Space-pad to 16 bytes */
765 i = len;
766 while (i & 0xf)
767 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200768
Denys Vlasenko76325802013-02-22 14:47:39 +0100769 i = 0;
770 src = str;
771 while (i < len) {
772 char *dst = outbuf;
773 /* Hex dump */
774 do {
775 if (i < len) {
776 *dst++ = "0123456789abcdef"[*src >> 4];
777 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 }
779 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100780 *dst++ = ' ';
781 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100783 dst++; /* space is there by memset */
784 i++;
785 if ((i & 7) == 0)
786 dst++; /* space is there by memset */
787 src++;
788 } while (i & 0xf);
789 /* ASCII dump */
790 i -= 16;
791 src -= 16;
792 do {
793 if (*src >= ' ' && *src < 0x7f)
794 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000795 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100796 *dst++ = '.';
797 src++;
798 } while (++i & 0xf);
799 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100800 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801 }
802}
803
Mike Frysinger612659e2012-02-14 14:38:28 +0100804#ifdef HAVE_PROCESS_VM_READV
805/* C library supports this, but the kernel might not. */
806static bool process_vm_readv_not_supported = 0;
807#else
808
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100809/* Need to do this since process_vm_readv() is not yet available in libc.
810 * When libc is be updated, only "static bool process_vm_readv_not_supported"
811 * line should remain.
812 */
813#if !defined(__NR_process_vm_readv)
814# if defined(I386)
815# define __NR_process_vm_readv 347
816# elif defined(X86_64)
817# define __NR_process_vm_readv 310
818# elif defined(POWERPC)
819# define __NR_process_vm_readv 351
820# endif
821#endif
822
823#if defined(__NR_process_vm_readv)
824static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400825/* Have to avoid duplicating with the C library headers. */
826static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100827 const struct iovec *lvec,
828 unsigned long liovcnt,
829 const struct iovec *rvec,
830 unsigned long riovcnt,
831 unsigned long flags)
832{
833 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
834}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400835#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100836#else
837static bool process_vm_readv_not_supported = 1;
838# define process_vm_readv(...) (errno = ENOSYS, -1)
839#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100840
841#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100842
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000843#define PAGMASK (~(PAGSIZ - 1))
844/*
845 * move `len' bytes of data from process `pid'
846 * at address `addr' to our space at `laddr'
847 */
848int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000849umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700851 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000852 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853 union {
854 long val;
855 char x[sizeof(long)];
856 } u;
857
Denys Vlasenko2544f982013-02-19 17:39:56 +0100858#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100859 if (current_wordsize < sizeof(addr))
860 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100861#endif
862
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100863 if (!process_vm_readv_not_supported) {
864 struct iovec local[1], remote[1];
865 int r;
866
867 local[0].iov_base = laddr;
868 remote[0].iov_base = (void*)addr;
869 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000870 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100871 if (r == len)
872 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000873 if (r >= 0) {
874 error_msg("umoven: short read (%d < %d) @0x%lx",
875 r, len, addr);
876 return -1;
877 }
878 switch (errno) {
879 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100880 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000881 break;
882 case ESRCH:
883 /* the process is gone */
884 return -1;
885 case EFAULT: case EIO: case EPERM:
886 /* address space is inaccessible */
887 return -1;
888 default:
889 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100890 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000891 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100892 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100893 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100894
Dmitry V. Levin97005922013-02-26 21:16:22 +0000895 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 if (addr & (sizeof(long) - 1)) {
897 /* addr not a multiple of sizeof(long) */
898 n = addr - (addr & -sizeof(long)); /* residue */
899 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700900 errno = 0;
901 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000902 switch (errno) {
903 case 0:
904 break;
905 case ESRCH: case EINVAL:
906 /* these could be seen if the process is gone */
907 return -1;
908 case EFAULT: case EIO: case EPERM:
909 /* address space is inaccessible */
910 return -1;
911 default:
912 /* all the rest is strange and should be reported */
913 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
914 pid, addr);
915 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700916 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100917 m = MIN(sizeof(long) - n, len);
918 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100919 addr += sizeof(long);
920 laddr += m;
921 nread += m;
922 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 }
924 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700925 errno = 0;
926 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000927 switch (errno) {
928 case 0:
929 break;
930 case ESRCH: case EINVAL:
931 /* these could be seen if the process is gone */
932 return -1;
933 case EFAULT: case EIO: case EPERM:
934 /* address space is inaccessible */
935 if (nread) {
936 perror_msg("umoven: short read (%d < %d) @0x%lx",
937 nread, nread + len, addr - nread);
938 }
939 return -1;
940 default:
941 /* all the rest is strange and should be reported */
942 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
943 pid, addr);
944 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700945 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100946 m = MIN(sizeof(long), len);
947 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100948 addr += sizeof(long);
949 laddr += m;
950 nread += m;
951 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 return 0;
955}
956
957/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100958 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100960 *
961 * Returns < 0 on error, > 0 if NUL was seen,
962 * (TODO if useful: return count of bytes including NUL),
963 * else 0 if len bytes were read but no NUL byte seen.
964 *
965 * Note: there is no guarantee we won't overwrite some bytes
966 * in laddr[] _after_ terminating NUL (but, of course,
967 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 */
969int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000970umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971{
Denys Vlasenko16940922013-03-01 18:52:59 +0100972#if SIZEOF_LONG == 4
973 const unsigned long x01010101 = 0x01010101ul;
974 const unsigned long x80808080 = 0x80808080ul;
975#elif SIZEOF_LONG == 8
976 const unsigned long x01010101 = 0x0101010101010101ul;
977 const unsigned long x80808080 = 0x8080808080808080ul;
978#else
979# error SIZEOF_LONG > 8
980#endif
981
Roland McGratheb9e2e82009-06-02 16:49:22 -0700982 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100983 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100985 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 char x[sizeof(long)];
987 } u;
988
Denys Vlasenko2544f982013-02-19 17:39:56 +0100989#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100990 if (current_wordsize < sizeof(addr))
991 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000992#endif
993
Dmitry V. Levin97005922013-02-26 21:16:22 +0000994 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100995 if (!process_vm_readv_not_supported) {
996 struct iovec local[1], remote[1];
997
998 local[0].iov_base = laddr;
999 remote[0].iov_base = (void*)addr;
1000
1001 while (len > 0) {
1002 int end_in_page;
1003 int r;
1004 int chunk_len;
1005
1006 /* Don't read kilobytes: most strings are short */
1007 chunk_len = len;
1008 if (chunk_len > 256)
1009 chunk_len = 256;
1010 /* Don't cross pages. I guess otherwise we can get EFAULT
1011 * and fail to notice that terminating NUL lies
1012 * in the existing (first) page.
1013 * (I hope there aren't arches with pages < 4K)
1014 */
1015 end_in_page = ((addr + chunk_len) & 4095);
1016 r = chunk_len - end_in_page;
1017 if (r > 0) /* if chunk_len > end_in_page */
1018 chunk_len = r; /* chunk_len -= end_in_page */
1019
1020 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001021 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1022 if (r > 0) {
1023 if (memchr(local[0].iov_base, '\0', r))
1024 return 1;
1025 local[0].iov_base += r;
1026 remote[0].iov_base += r;
1027 len -= r;
1028 nread += r;
1029 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001030 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001031 switch (errno) {
1032 case ENOSYS:
1033 process_vm_readv_not_supported = 1;
1034 goto vm_readv_didnt_work;
1035 case ESRCH:
1036 /* the process is gone */
1037 return -1;
1038 case EFAULT: case EIO: case EPERM:
1039 /* address space is inaccessible */
1040 if (nread) {
1041 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1042 nread, nread + len, addr);
1043 }
1044 return -1;
1045 default:
1046 /* all the rest is strange and should be reported */
1047 perror_msg("process_vm_readv");
1048 return -1;
1049 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001050 }
1051 return 0;
1052 }
1053 vm_readv_didnt_work:
1054
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 if (addr & (sizeof(long) - 1)) {
1056 /* addr not a multiple of sizeof(long) */
1057 n = addr - (addr & -sizeof(long)); /* residue */
1058 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001059 errno = 0;
1060 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001061 switch (errno) {
1062 case 0:
1063 break;
1064 case ESRCH: case EINVAL:
1065 /* these could be seen if the process is gone */
1066 return -1;
1067 case EFAULT: case EIO: case EPERM:
1068 /* address space is inaccessible */
1069 return -1;
1070 default:
1071 /* all the rest is strange and should be reported */
1072 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1073 pid, addr);
1074 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001075 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001076 m = MIN(sizeof(long) - n, len);
1077 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 while (n & (sizeof(long) - 1))
1079 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001080 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001081 addr += sizeof(long);
1082 laddr += m;
1083 nread += m;
1084 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001088 errno = 0;
1089 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001090 switch (errno) {
1091 case 0:
1092 break;
1093 case ESRCH: case EINVAL:
1094 /* these could be seen if the process is gone */
1095 return -1;
1096 case EFAULT: case EIO: case EPERM:
1097 /* address space is inaccessible */
1098 if (nread) {
1099 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1100 nread, nread + len, addr - nread);
1101 }
1102 return -1;
1103 default:
1104 /* all the rest is strange and should be reported */
1105 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1106 pid, addr);
1107 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001108 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001109 m = MIN(sizeof(long), len);
1110 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001111 /* "If a NUL char exists in this word" */
1112 if ((u.val - x01010101) & ~u.val & x80808080)
1113 return 1;
1114 addr += sizeof(long);
1115 laddr += m;
1116 nread += m;
1117 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001119 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120}
1121
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001123upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124{
1125 long val;
1126
Roland McGratheb9e2e82009-06-02 16:49:22 -07001127 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001128 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001129 if (val == -1 && errno) {
1130 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001131 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001132 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001134 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 *res = val;
1136 return 0;
1137}
1138
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001139/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1140 * and PTRACE_O_TRACE[V]FORK for tracing children.
1141 * If you are adding a new arch which is only supported by newer kernels,
1142 * you most likely don't need to add any code below
1143 * beside a dummy "return 0" block in change_syscall().
1144 */
1145
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001146/*
1147 * These #if's are huge, please indent them correctly.
1148 * It's easy to get confused otherwise.
1149 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001151#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001152
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001153#ifndef CLONE_PTRACE
1154# define CLONE_PTRACE 0x00002000
1155#endif
1156#ifndef CLONE_VFORK
1157# define CLONE_VFORK 0x00004000
1158#endif
1159#ifndef CLONE_VM
1160# define CLONE_VM 0x00000100
1161#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001162
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001163#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001164
1165typedef unsigned long *arg_setup_state;
1166
1167static int
1168arg_setup(struct tcb *tcp, arg_setup_state *state)
1169{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001170 unsigned long cfm, sof, sol;
1171 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001173 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001174 /* Satisfy a false GCC warning. */
1175 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001176 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001177 }
Roland McGrath08267b82004-02-20 22:56:43 +00001178
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001179 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001181 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182 return -1;
1183
1184 sof = (cfm >> 0) & 0x7f;
1185 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001186 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001187
Jan Kratochvil1f942712008-08-06 21:38:52 +00001188 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001189 return 0;
1190}
1191
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001192# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001193
Roland McGrathd81f1d92003-01-09 06:53:34 +00001194static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001195get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001196{
Roland McGrath08267b82004-02-20 22:56:43 +00001197 int ret;
1198
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001199 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001200 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001201 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001202 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001203 (unsigned long) ia64_rse_skip_regs(*state, 0),
1204 sizeof(long), (void *) valp);
1205 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206}
1207
1208static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001209get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210{
Roland McGrath08267b82004-02-20 22:56:43 +00001211 int ret;
1212
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001213 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001214 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001215 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001216 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001217 (unsigned long) ia64_rse_skip_regs(*state, 1),
1218 sizeof(long), (void *) valp);
1219 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001221
1222static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001223set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001224{
Roland McGrath08267b82004-02-20 22:56:43 +00001225 int req = PTRACE_POKEDATA;
1226 void *ap;
1227
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001228 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001229 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1230 req = PTRACE_POKEUSER;
1231 } else
1232 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001233 errno = 0;
1234 ptrace(req, tcp->pid, ap, val);
1235 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001236}
1237
1238static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001239set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001240{
Roland McGrath08267b82004-02-20 22:56:43 +00001241 int req = PTRACE_POKEDATA;
1242 void *ap;
1243
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001244 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001245 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1246 req = PTRACE_POKEUSER;
1247 } else
1248 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001249 errno = 0;
1250 ptrace(req, tcp->pid, ap, val);
1251 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252}
1253
Roland McGrathb659f872008-07-18 01:19:36 +00001254/* ia64 does not return the input arguments from functions (and syscalls)
1255 according to ia64 RSE (Register Stack Engine) behavior. */
1256
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001257# define restore_arg0(tcp, state, val) ((void) (state), 0)
1258# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001259
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001260#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001262# if defined(SPARC64)
1263# undef PTRACE_GETREGS
1264# define PTRACE_GETREGS PTRACE_GETREGS64
1265# undef PTRACE_SETREGS
1266# define PTRACE_SETREGS PTRACE_SETREGS64
1267# endif
1268
Mike Frysinger8566c502009-10-12 11:05:14 -04001269typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001271# define arg_setup(tcp, state) \
1272 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1273# define arg_finish_change(tcp, state) \
1274 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001276# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1277# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1278# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1279# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1280# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001282#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001284# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001285/* Note: this is only true for the `clone' system call, which handles
1286 arguments specially. We could as well say that its first two arguments
1287 are swapped relative to other architectures, but that would just be
1288 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001289# define arg0_offset PT_GPR3
1290# define arg1_offset PT_ORIGGPR2
1291# define restore_arg0(tcp, state, val) ((void) (state), 0)
1292# define restore_arg1(tcp, state, val) ((void) (state), 0)
1293# define arg0_index 1
1294# define arg1_index 0
1295# elif defined(ALPHA) || defined(MIPS)
1296# define arg0_offset REG_A0
1297# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001298# elif defined(POWERPC)
1299# define arg0_offset (sizeof(unsigned long)*PT_R3)
1300# define arg1_offset (sizeof(unsigned long)*PT_R4)
1301# define restore_arg0(tcp, state, val) ((void) (state), 0)
1302# elif defined(HPPA)
1303# define arg0_offset PT_GR26
1304# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001305# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001306# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1307# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1308# elif defined(SH)
1309# define arg0_offset (4*(REG_REG0+4))
1310# define arg1_offset (4*(REG_REG0+5))
1311# elif defined(SH64)
1312 /* ABI defines arg0 & 1 in r2 & r3 */
1313# define arg0_offset (REG_OFFSET+16)
1314# define arg1_offset (REG_OFFSET+24)
1315# define restore_arg0(tcp, state, val) 0
1316# elif defined CRISV10 || defined CRISV32
1317# define arg0_offset (4*PT_R11)
1318# define arg1_offset (4*PT_ORIG_R10)
1319# define restore_arg0(tcp, state, val) 0
1320# define restore_arg1(tcp, state, val) 0
1321# define arg0_index 1
1322# define arg1_index 0
1323# else
1324# define arg0_offset 0
1325# define arg1_offset 4
1326# if defined ARM
1327# define restore_arg0(tcp, state, val) 0
1328# endif
1329# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330
1331typedef int arg_setup_state;
1332
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001333# define arg_setup(tcp, state) (0)
1334# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001335# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1336# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337
1338static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001339set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001341 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342}
1343
1344static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001345set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001346{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001347 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348}
1349
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001350#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001352#ifndef restore_arg0
1353# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1354#endif
1355#ifndef restore_arg1
1356# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1357#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001359#ifndef arg0_index
1360# define arg0_index 0
1361# define arg1_index 1
1362#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001363
James Hogan05eb9052012-11-29 17:37:37 +00001364static int
1365change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1366{
1367#if defined(I386)
1368 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1369 return -1;
1370 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001371#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001372 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1373 return -1;
1374 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001375#elif defined(X32)
1376 /* setbpt/clearbpt never used: */
1377 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001378#elif defined(POWERPC)
1379 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1380 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1381 return -1;
1382 return 0;
1383#elif defined(S390) || defined(S390X)
1384 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1385 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1386 return -1;
1387 return 0;
1388#elif defined(M68K)
1389 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1390 return -1;
1391 return 0;
1392#elif defined(SPARC) || defined(SPARC64)
1393 state->u_regs[U_REG_G1] = new;
1394 return 0;
1395#elif defined(MIPS)
1396 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1397 return -1;
1398 return 0;
1399#elif defined(ALPHA)
1400 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1401 return -1;
1402 return 0;
1403#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001404 /* setbpt/clearbpt never used: */
1405 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001406#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001407 /* setbpt/clearbpt never used: */
1408 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001409#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001410 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001411 switch (new) {
1412 case 2:
1413 break; /* x86 SYS_fork */
1414 case SYS_clone:
1415 new = 120;
1416 break;
1417 default:
1418 fprintf(stderr, "%s: unexpected syscall %d\n",
1419 __FUNCTION__, new);
1420 return -1;
1421 }
1422 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1423 return -1;
1424 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1425 return -1;
1426 return 0;
1427#elif defined(HPPA)
1428 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1429 return -1;
1430 return 0;
1431#elif defined(SH)
1432 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1433 return -1;
1434 return 0;
1435#elif defined(SH64)
1436 /* Top half of reg encodes the no. of args n as 0x1n.
1437 Assume 0 args as kernel never actually checks... */
1438 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1439 0x100000 | new) < 0)
1440 return -1;
1441 return 0;
1442#elif defined(CRISV10) || defined(CRISV32)
1443 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1444 return -1;
1445 return 0;
1446#elif defined(ARM)
1447 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1448# ifndef PTRACE_SET_SYSCALL
1449# define PTRACE_SET_SYSCALL 23
1450# endif
1451 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1452 return -1;
1453 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001454#elif defined(AARCH64)
1455 /* setbpt/clearbpt never used: */
1456 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001457#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001458 /* setbpt/clearbpt never used: */
1459 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001460#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001461 /* setbpt/clearbpt never used: */
1462 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001463#elif defined(OR1K)
1464 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001465#elif defined(METAG)
1466 /* setbpt/clearbpt never used: */
1467 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001468#elif defined(XTENSA)
1469 /* setbpt/clearbpt never used: */
1470 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301471#elif defined(ARC)
1472 /* setbpt/clearbpt never used: */
1473 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001474#else
1475#warning Do not know how to handle change_syscall for this architecture
1476#endif /* architecture */
1477 return -1;
1478}
1479
Roland McGrathd81f1d92003-01-09 06:53:34 +00001480int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001481setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001482{
Roland McGrath3291ef22008-05-20 00:34:34 +00001483 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484 arg_setup_state state;
1485
1486 if (tcp->flags & TCB_BPTSET) {
1487 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1488 return -1;
1489 }
1490
Roland McGrath3291ef22008-05-20 00:34:34 +00001491 /*
1492 * It's a silly kludge to initialize this with a search at runtime.
1493 * But it's better than maintaining another magic thing in the
1494 * godforsaken tables.
1495 */
1496 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001497 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001498 for (i = 0; i < nsyscalls; ++i)
1499 if (sysent[i].sys_func == sys_clone) {
1500 clone_scno[current_personality] = i;
1501 break;
1502 }
1503 }
1504
Dmitry V. Levin65563152014-05-12 13:43:10 +00001505 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001506 if (arg_setup(tcp, &state) < 0
1507 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1508 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001509 || change_syscall(tcp, &state,
1510 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001511 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1512 || set_arg1(tcp, &state, 0) < 0
1513 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001514 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001515 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1516 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001517 tcp->flags |= TCB_BPTSET;
1518 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001519 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001520
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001521 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001522 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001523 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001524 vfork semantics into plain fork - each application must not
1525 depend on the vfork specifics according to POSIX. We would
1526 hang waiting for the parent resume otherwise. We need to
1527 clear also CLONE_VM but only in the CLONE_VFORK case as
1528 otherwise we would break pthread_create. */
1529
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001530 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1531 if (new_arg0 & CLONE_VFORK)
1532 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1533 if (arg_setup(tcp, &state) < 0
1534 || set_arg0(tcp, &state, new_arg0) < 0
1535 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001536 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001537 tcp->inst[0] = tcp->u_arg[arg0_index];
1538 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001539 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001540 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001541 }
1542
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001543 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1544 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001545 return -1;
1546}
1547
1548int
Denys Vlasenko12014262011-05-30 14:00:14 +02001549clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001550{
1551 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001552 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001553 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001554 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1555 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1556 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001557 if (errno != ESRCH)
1558 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001559 tcp->flags &= ~TCB_BPTSET;
1560 return 0;
1561}