blob: 85bb94c92cd8b642607108d0c8f55a5b42ddb974 [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
Denys Vlasenko12014262011-05-30 14:00:14 +020082tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083{
84 return a->tv_sec || a->tv_usec;
85}
86
87int
Denys Vlasenko12014262011-05-30 14:00:14 +020088tv_cmp(struct timeval *a, 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
Denys Vlasenko12014262011-05-30 14:00:14 +0200100tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101{
102 return tv->tv_sec + tv->tv_usec/1000000.0;
103}
104
105void
Denys Vlasenko12014262011-05-30 14:00:14 +0200106tv_add(struct timeval *tv, struct timeval *a, 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
Denys Vlasenko12014262011-05-30 14:00:14 +0200117tv_sub(struct timeval *tv, struct timeval *a, 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
Denys Vlasenko12014262011-05-30 14:00:14 +0200128tv_div(struct timeval *tv, 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
Denys Vlasenko12014262011-05-30 14:00:14 +0200136tv_mul(struct timeval *tv, 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 *
144xlookup(const struct xlat *xlat, 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. Levinab9008b2007-01-11 22:05:04 +0000213printxval(const struct xlat *xlat, 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
Chris Metcalf879dddd2013-03-01 10:41:02 +0100228printllval(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. Levina55b6b12013-05-03 22:27:45 +0000239 /* Align arg_no to the next even number. */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100240 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. Levina55b6b12013-05-03 22:27:45 +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];
Grant Edwards8a082772011-04-07 20:25:40 +0000407
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100408 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
409 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000410 else
411 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300412}
413
414void
Denys Vlasenko12014262011-05-30 14:00:14 +0200415printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000416{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200417 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000418}
419
Dmitry V. Levina501f142008-11-10 23:19:13 +0000420/*
421 * Quote string `instr' of length `size'
422 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200423 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000424 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100425 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200426 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100427 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000428 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400429int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200430string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000431{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000432 const unsigned char *ustr = (const unsigned char *) instr;
433 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200434 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000435
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200436 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200437 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200438 size--;
439 eol = '\0';
440 }
441
442 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000443 if (xflag > 1)
444 usehex = 1;
445 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000446 /* Check for presence of symbol which require
447 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000448 for (i = 0; i < size; ++i) {
449 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000450 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200451 if (c == eol)
452 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100453
454 /* Force hex unless c is printable or whitespace */
455 if (c > 0x7e) {
456 usehex = 1;
457 break;
458 }
459 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
460 * They happen to have ASCII codes 9,10,11,12,13.
461 */
462 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000463 usehex = 1;
464 break;
465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 }
467 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000468
469 *s++ = '\"';
470
471 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000472 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000473 for (i = 0; i < size; ++i) {
474 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000475 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200476 if (c == eol)
477 goto asciz_ended;
478 *s++ = '\\';
479 *s++ = 'x';
480 *s++ = "0123456789abcdef"[c >> 4];
481 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000482 }
483 } else {
484 for (i = 0; i < size; ++i) {
485 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000486 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200487 if (c == eol)
488 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000489 switch (c) {
490 case '\"': case '\\':
491 *s++ = '\\';
492 *s++ = c;
493 break;
494 case '\f':
495 *s++ = '\\';
496 *s++ = 'f';
497 break;
498 case '\n':
499 *s++ = '\\';
500 *s++ = 'n';
501 break;
502 case '\r':
503 *s++ = '\\';
504 *s++ = 'r';
505 break;
506 case '\t':
507 *s++ = '\\';
508 *s++ = 't';
509 break;
510 case '\v':
511 *s++ = '\\';
512 *s++ = 'v';
513 break;
514 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100515 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000516 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200517 else {
518 /* Print \octal */
519 *s++ = '\\';
520 if (i + 1 < size
521 && ustr[i + 1] >= '0'
522 && ustr[i + 1] <= '9'
523 ) {
524 /* Print \ooo */
525 *s++ = '0' + (c >> 6);
526 *s++ = '0' + ((c >> 3) & 0x7);
527 } else {
528 /* Print \[[o]o]o */
529 if ((c >> 3) != 0) {
530 if ((c >> 6) != 0)
531 *s++ = '0' + (c >> 6);
532 *s++ = '0' + ((c >> 3) & 0x7);
533 }
534 }
535 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000536 }
537 break;
538 }
539 }
540 }
541
542 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000544
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200545 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200546 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200547 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
548 * but next char is NUL.
549 */
550 return 0;
551 }
552
553 return 1;
554
555 asciz_ended:
556 *s++ = '\"';
557 *s = '\0';
558 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
559 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560}
561
Dmitry V. Levina501f142008-11-10 23:19:13 +0000562/*
563 * Print path string specified by address `addr' and length `n'.
564 * If path length exceeds `n', append `...' to the output.
565 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100569 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100570 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100571
Dmitry V. Levina501f142008-11-10 23:19:13 +0000572 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200573 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574 return;
575 }
576
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100577 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000578 if (n > sizeof path - 1)
579 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000580
581 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100582 nul_seen = umovestr(tcp, addr, n + 1, path);
583 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 tprintf("%#lx", addr);
585 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100586 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000587
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100588 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100589 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100590 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100591 string_quote(path, outstr, -1, n);
592 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100593 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100594 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000595 }
596}
597
598void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000599printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100601 /* Size must correspond to char path[] size in printpathn */
602 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000603}
604
Dmitry V. Levina501f142008-11-10 23:19:13 +0000605/*
606 * Print string specified by address `addr' and length `len'.
607 * If `len' < 0, treat the string as a NUL-terminated string.
608 * If string length exceeds `max_strlen', append `...' to the output.
609 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000610void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200611printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000612{
613 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000615 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100616 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000617
618 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200619 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000620 return;
621 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000622 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200623 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000624 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
625
626 if (outstr_size / 4 != max_strlen)
627 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000628 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200629 if (!str)
630 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000631 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200632 if (!outstr)
633 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000634 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000635
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200636 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000637 /*
638 * Treat as a NUL-terminated string: fetch one byte more
639 * because string_quote() quotes one byte less.
640 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000641 size = max_strlen + 1;
642 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000643 tprintf("%#lx", addr);
644 return;
645 }
646 }
647 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200648 size = max_strlen;
649 if (size > (unsigned long)len)
650 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000651 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652 tprintf("%#lx", addr);
653 return;
654 }
655 }
656
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100657 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
658 * or we were requested to print more than -s NUM chars)...
659 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100660 ellipsis = (string_quote(str, outstr, len, size) &&
661 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000662
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100663 tprints(outstr);
664 if (ellipsis)
665 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666}
667
John Hughes1d08dcf2001-07-10 13:48:44 +0000668#if HAVE_SYS_UIO_H
669void
Denys Vlasenko12014262011-05-30 14:00:14 +0200670dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000671{
Denys Vlasenko84703742012-02-25 02:38:52 +0100672#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000673 union {
674 struct { u_int32_t base; u_int32_t len; } *iov32;
675 struct { u_int64_t base; u_int64_t len; } *iov64;
676 } iovu;
677#define iov iovu.iov64
678#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100679 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000680#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100681 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000682#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100683 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000684#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000685 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000686#define sizeof_iov sizeof(*iov)
687#define iov_iov_base(i) iov[i].iov_base
688#define iov_iov_len(i) iov[i].iov_len
689#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000690 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200691 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000692
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200693 size = sizeof_iov * len;
694 /* Assuming no sane program has millions of iovs */
695 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000696 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200697 fprintf(stderr, "Out of memory\n");
698 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000699 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000700 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000701 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000702 /* include the buffer number to make it easy to
703 * match up the trace with the source */
704 tprintf(" * %lu bytes in buffer %d\n",
705 (unsigned long)iov_iov_len(i), i);
706 dumpstr(tcp, (long) iov_iov_base(i),
707 iov_iov_len(i));
708 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000709 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200710 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000711#undef sizeof_iov
712#undef iov_iov_base
713#undef iov_iov_len
714#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000715}
716#endif
717
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718void
Denys Vlasenko12014262011-05-30 14:00:14 +0200719dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720{
721 static int strsize = -1;
722 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723
Denys Vlasenko76325802013-02-22 14:47:39 +0100724 char outbuf[
725 (
726 (sizeof(
727 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
728 "1234567890123456") + /*in case I'm off by few:*/ 4)
729 /*align to 8 to make memset easier:*/ + 7) & -8
730 ];
731 const unsigned char *src;
732 int i;
733
734 memset(outbuf, ' ', sizeof(outbuf));
735
736 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200737 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100738 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200739 if (!str) {
740 strsize = -1;
741 fprintf(stderr, "Out of memory\n");
742 return;
743 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100744 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745 }
746
747 if (umoven(tcp, addr, len, (char *) str) < 0)
748 return;
749
Denys Vlasenko76325802013-02-22 14:47:39 +0100750 /* Space-pad to 16 bytes */
751 i = len;
752 while (i & 0xf)
753 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200754
Denys Vlasenko76325802013-02-22 14:47:39 +0100755 i = 0;
756 src = str;
757 while (i < len) {
758 char *dst = outbuf;
759 /* Hex dump */
760 do {
761 if (i < len) {
762 *dst++ = "0123456789abcdef"[*src >> 4];
763 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000764 }
765 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100766 *dst++ = ' ';
767 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100769 dst++; /* space is there by memset */
770 i++;
771 if ((i & 7) == 0)
772 dst++; /* space is there by memset */
773 src++;
774 } while (i & 0xf);
775 /* ASCII dump */
776 i -= 16;
777 src -= 16;
778 do {
779 if (*src >= ' ' && *src < 0x7f)
780 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100782 *dst++ = '.';
783 src++;
784 } while (++i & 0xf);
785 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100786 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 }
788}
789
Mike Frysinger612659e2012-02-14 14:38:28 +0100790#ifdef HAVE_PROCESS_VM_READV
791/* C library supports this, but the kernel might not. */
792static bool process_vm_readv_not_supported = 0;
793#else
794
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100795/* Need to do this since process_vm_readv() is not yet available in libc.
796 * When libc is be updated, only "static bool process_vm_readv_not_supported"
797 * line should remain.
798 */
799#if !defined(__NR_process_vm_readv)
800# if defined(I386)
801# define __NR_process_vm_readv 347
802# elif defined(X86_64)
803# define __NR_process_vm_readv 310
804# elif defined(POWERPC)
805# define __NR_process_vm_readv 351
806# endif
807#endif
808
809#if defined(__NR_process_vm_readv)
810static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400811/* Have to avoid duplicating with the C library headers. */
812static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100813 const struct iovec *lvec,
814 unsigned long liovcnt,
815 const struct iovec *rvec,
816 unsigned long riovcnt,
817 unsigned long flags)
818{
819 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
820}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400821#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100822#else
823static bool process_vm_readv_not_supported = 1;
824# define process_vm_readv(...) (errno = ENOSYS, -1)
825#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100826
827#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100828
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829#define PAGMASK (~(PAGSIZ - 1))
830/*
831 * move `len' bytes of data from process `pid'
832 * at address `addr' to our space at `laddr'
833 */
834int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000835umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700837 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000838 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839 union {
840 long val;
841 char x[sizeof(long)];
842 } u;
843
Denys Vlasenko2544f982013-02-19 17:39:56 +0100844#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100845 if (current_wordsize < sizeof(addr))
846 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100847#endif
848
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100849 if (!process_vm_readv_not_supported) {
850 struct iovec local[1], remote[1];
851 int r;
852
853 local[0].iov_base = laddr;
854 remote[0].iov_base = (void*)addr;
855 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000856 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100857 if (r == len)
858 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000859 if (r >= 0) {
860 error_msg("umoven: short read (%d < %d) @0x%lx",
861 r, len, addr);
862 return -1;
863 }
864 switch (errno) {
865 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100866 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000867 break;
868 case ESRCH:
869 /* the process is gone */
870 return -1;
871 case EFAULT: case EIO: case EPERM:
872 /* address space is inaccessible */
873 return -1;
874 default:
875 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100876 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000877 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100878 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100879 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100880
Dmitry V. Levin97005922013-02-26 21:16:22 +0000881 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 if (addr & (sizeof(long) - 1)) {
883 /* addr not a multiple of sizeof(long) */
884 n = addr - (addr & -sizeof(long)); /* residue */
885 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700886 errno = 0;
887 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000888 switch (errno) {
889 case 0:
890 break;
891 case ESRCH: case EINVAL:
892 /* these could be seen if the process is gone */
893 return -1;
894 case EFAULT: case EIO: case EPERM:
895 /* address space is inaccessible */
896 return -1;
897 default:
898 /* all the rest is strange and should be reported */
899 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
900 pid, addr);
901 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700902 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100903 m = MIN(sizeof(long) - n, len);
904 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100905 addr += sizeof(long);
906 laddr += m;
907 nread += m;
908 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 }
910 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700911 errno = 0;
912 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000913 switch (errno) {
914 case 0:
915 break;
916 case ESRCH: case EINVAL:
917 /* these could be seen if the process is gone */
918 return -1;
919 case EFAULT: case EIO: case EPERM:
920 /* address space is inaccessible */
921 if (nread) {
922 perror_msg("umoven: short read (%d < %d) @0x%lx",
923 nread, nread + len, addr - nread);
924 }
925 return -1;
926 default:
927 /* all the rest is strange and should be reported */
928 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
929 pid, addr);
930 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700931 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100932 m = MIN(sizeof(long), len);
933 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100934 addr += sizeof(long);
935 laddr += m;
936 nread += m;
937 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 return 0;
941}
942
943/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100944 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100946 *
947 * Returns < 0 on error, > 0 if NUL was seen,
948 * (TODO if useful: return count of bytes including NUL),
949 * else 0 if len bytes were read but no NUL byte seen.
950 *
951 * Note: there is no guarantee we won't overwrite some bytes
952 * in laddr[] _after_ terminating NUL (but, of course,
953 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 */
955int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000956umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957{
Denys Vlasenko16940922013-03-01 18:52:59 +0100958#if SIZEOF_LONG == 4
959 const unsigned long x01010101 = 0x01010101ul;
960 const unsigned long x80808080 = 0x80808080ul;
961#elif SIZEOF_LONG == 8
962 const unsigned long x01010101 = 0x0101010101010101ul;
963 const unsigned long x80808080 = 0x8080808080808080ul;
964#else
965# error SIZEOF_LONG > 8
966#endif
967
Roland McGratheb9e2e82009-06-02 16:49:22 -0700968 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100969 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100971 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 char x[sizeof(long)];
973 } u;
974
Denys Vlasenko2544f982013-02-19 17:39:56 +0100975#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100976 if (current_wordsize < sizeof(addr))
977 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000978#endif
979
Dmitry V. Levin97005922013-02-26 21:16:22 +0000980 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100981 if (!process_vm_readv_not_supported) {
982 struct iovec local[1], remote[1];
983
984 local[0].iov_base = laddr;
985 remote[0].iov_base = (void*)addr;
986
987 while (len > 0) {
988 int end_in_page;
989 int r;
990 int chunk_len;
991
992 /* Don't read kilobytes: most strings are short */
993 chunk_len = len;
994 if (chunk_len > 256)
995 chunk_len = 256;
996 /* Don't cross pages. I guess otherwise we can get EFAULT
997 * and fail to notice that terminating NUL lies
998 * in the existing (first) page.
999 * (I hope there aren't arches with pages < 4K)
1000 */
1001 end_in_page = ((addr + chunk_len) & 4095);
1002 r = chunk_len - end_in_page;
1003 if (r > 0) /* if chunk_len > end_in_page */
1004 chunk_len = r; /* chunk_len -= end_in_page */
1005
1006 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001007 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1008 if (r > 0) {
1009 if (memchr(local[0].iov_base, '\0', r))
1010 return 1;
1011 local[0].iov_base += r;
1012 remote[0].iov_base += r;
1013 len -= r;
1014 nread += r;
1015 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001016 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001017 switch (errno) {
1018 case ENOSYS:
1019 process_vm_readv_not_supported = 1;
1020 goto vm_readv_didnt_work;
1021 case ESRCH:
1022 /* the process is gone */
1023 return -1;
1024 case EFAULT: case EIO: case EPERM:
1025 /* address space is inaccessible */
1026 if (nread) {
1027 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1028 nread, nread + len, addr);
1029 }
1030 return -1;
1031 default:
1032 /* all the rest is strange and should be reported */
1033 perror_msg("process_vm_readv");
1034 return -1;
1035 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001036 }
1037 return 0;
1038 }
1039 vm_readv_didnt_work:
1040
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 if (addr & (sizeof(long) - 1)) {
1042 /* addr not a multiple of sizeof(long) */
1043 n = addr - (addr & -sizeof(long)); /* residue */
1044 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001045 errno = 0;
1046 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001047 switch (errno) {
1048 case 0:
1049 break;
1050 case ESRCH: case EINVAL:
1051 /* these could be seen if the process is gone */
1052 return -1;
1053 case EFAULT: case EIO: case EPERM:
1054 /* address space is inaccessible */
1055 return -1;
1056 default:
1057 /* all the rest is strange and should be reported */
1058 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1059 pid, addr);
1060 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001061 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001062 m = MIN(sizeof(long) - n, len);
1063 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 while (n & (sizeof(long) - 1))
1065 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001066 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001067 addr += sizeof(long);
1068 laddr += m;
1069 nread += m;
1070 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001072
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001074 errno = 0;
1075 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001076 switch (errno) {
1077 case 0:
1078 break;
1079 case ESRCH: case EINVAL:
1080 /* these could be seen if the process is gone */
1081 return -1;
1082 case EFAULT: case EIO: case EPERM:
1083 /* address space is inaccessible */
1084 if (nread) {
1085 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1086 nread, nread + len, addr - nread);
1087 }
1088 return -1;
1089 default:
1090 /* all the rest is strange and should be reported */
1091 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1092 pid, addr);
1093 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001094 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001095 m = MIN(sizeof(long), len);
1096 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001097 /* "If a NUL char exists in this word" */
1098 if ((u.val - x01010101) & ~u.val & x80808080)
1099 return 1;
1100 addr += sizeof(long);
1101 laddr += m;
1102 nread += m;
1103 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001105 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106}
1107
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001109upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110{
1111 long val;
1112
Roland McGratheb9e2e82009-06-02 16:49:22 -07001113 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001114 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001115 if (val == -1 && errno) {
1116 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001117 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001118 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001120 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 *res = val;
1122 return 0;
1123}
1124
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001125/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1126 * and PTRACE_O_TRACE[V]FORK for tracing children.
1127 * If you are adding a new arch which is only supported by newer kernels,
1128 * you most likely don't need to add any code below
1129 * beside a dummy "return 0" block in change_syscall().
1130 */
1131
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001132/*
1133 * These #if's are huge, please indent them correctly.
1134 * It's easy to get confused otherwise.
1135 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001137#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001138
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001139#ifndef CLONE_PTRACE
1140# define CLONE_PTRACE 0x00002000
1141#endif
1142#ifndef CLONE_VFORK
1143# define CLONE_VFORK 0x00004000
1144#endif
1145#ifndef CLONE_VM
1146# define CLONE_VM 0x00000100
1147#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001148
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001149#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001150
1151typedef unsigned long *arg_setup_state;
1152
1153static int
1154arg_setup(struct tcb *tcp, arg_setup_state *state)
1155{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001156 unsigned long cfm, sof, sol;
1157 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001158
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001159 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001160 /* Satisfy a false GCC warning. */
1161 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001162 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001163 }
Roland McGrath08267b82004-02-20 22:56:43 +00001164
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001165 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001166 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001167 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001168 return -1;
1169
1170 sof = (cfm >> 0) & 0x7f;
1171 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001172 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001173
Jan Kratochvil1f942712008-08-06 21:38:52 +00001174 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001175 return 0;
1176}
1177
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001178# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001179
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001181get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182{
Roland McGrath08267b82004-02-20 22:56:43 +00001183 int ret;
1184
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001185 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001186 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001187 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001188 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001189 (unsigned long) ia64_rse_skip_regs(*state, 0),
1190 sizeof(long), (void *) valp);
1191 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001192}
1193
1194static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001195get_arg1(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_R9, 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, 1),
1204 sizeof(long), (void *) valp);
1205 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001207
1208static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001209set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210{
Roland McGrath08267b82004-02-20 22:56:43 +00001211 int req = PTRACE_POKEDATA;
1212 void *ap;
1213
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001214 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001215 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1216 req = PTRACE_POKEUSER;
1217 } else
1218 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001219 errno = 0;
1220 ptrace(req, tcp->pid, ap, val);
1221 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001222}
1223
1224static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001225set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226{
Roland McGrath08267b82004-02-20 22:56:43 +00001227 int req = PTRACE_POKEDATA;
1228 void *ap;
1229
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001230 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001231 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1232 req = PTRACE_POKEUSER;
1233 } else
1234 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001235 errno = 0;
1236 ptrace(req, tcp->pid, ap, val);
1237 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001238}
1239
Roland McGrathb659f872008-07-18 01:19:36 +00001240/* ia64 does not return the input arguments from functions (and syscalls)
1241 according to ia64 RSE (Register Stack Engine) behavior. */
1242
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001243# define restore_arg0(tcp, state, val) ((void) (state), 0)
1244# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001245
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001246#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001247
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001248# if defined(SPARC64)
1249# undef PTRACE_GETREGS
1250# define PTRACE_GETREGS PTRACE_GETREGS64
1251# undef PTRACE_SETREGS
1252# define PTRACE_SETREGS PTRACE_SETREGS64
1253# endif
1254
Mike Frysinger8566c502009-10-12 11:05:14 -04001255typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001256
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001257# define arg_setup(tcp, state) \
1258 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1259# define arg_finish_change(tcp, state) \
1260 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001262# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1263# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1264# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1265# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1266# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001267
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001268#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001270# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001271/* Note: this is only true for the `clone' system call, which handles
1272 arguments specially. We could as well say that its first two arguments
1273 are swapped relative to other architectures, but that would just be
1274 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001275# define arg0_offset PT_GPR3
1276# define arg1_offset PT_ORIGGPR2
1277# define restore_arg0(tcp, state, val) ((void) (state), 0)
1278# define restore_arg1(tcp, state, val) ((void) (state), 0)
1279# define arg0_index 1
1280# define arg1_index 0
1281# elif defined(ALPHA) || defined(MIPS)
1282# define arg0_offset REG_A0
1283# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001284# elif defined(POWERPC)
1285# define arg0_offset (sizeof(unsigned long)*PT_R3)
1286# define arg1_offset (sizeof(unsigned long)*PT_R4)
1287# define restore_arg0(tcp, state, val) ((void) (state), 0)
1288# elif defined(HPPA)
1289# define arg0_offset PT_GR26
1290# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001291# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001292# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1293# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1294# elif defined(SH)
1295# define arg0_offset (4*(REG_REG0+4))
1296# define arg1_offset (4*(REG_REG0+5))
1297# elif defined(SH64)
1298 /* ABI defines arg0 & 1 in r2 & r3 */
1299# define arg0_offset (REG_OFFSET+16)
1300# define arg1_offset (REG_OFFSET+24)
1301# define restore_arg0(tcp, state, val) 0
1302# elif defined CRISV10 || defined CRISV32
1303# define arg0_offset (4*PT_R11)
1304# define arg1_offset (4*PT_ORIG_R10)
1305# define restore_arg0(tcp, state, val) 0
1306# define restore_arg1(tcp, state, val) 0
1307# define arg0_index 1
1308# define arg1_index 0
1309# else
1310# define arg0_offset 0
1311# define arg1_offset 4
1312# if defined ARM
1313# define restore_arg0(tcp, state, val) 0
1314# endif
1315# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001316
1317typedef int arg_setup_state;
1318
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001319# define arg_setup(tcp, state) (0)
1320# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001321# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1322# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001323
1324static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001325set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001326{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001327 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001328}
1329
1330static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001331set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001333 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001334}
1335
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001336#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001338#ifndef restore_arg0
1339# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1340#endif
1341#ifndef restore_arg1
1342# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1343#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001344
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001345#ifndef arg0_index
1346# define arg0_index 0
1347# define arg1_index 1
1348#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001349
James Hogan05eb9052012-11-29 17:37:37 +00001350static int
1351change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1352{
1353#if defined(I386)
1354 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1355 return -1;
1356 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001357#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001358 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1359 return -1;
1360 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001361#elif defined(X32)
1362 /* setbpt/clearbpt never used: */
1363 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001364#elif defined(POWERPC)
1365 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1366 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1367 return -1;
1368 return 0;
1369#elif defined(S390) || defined(S390X)
1370 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1371 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1372 return -1;
1373 return 0;
1374#elif defined(M68K)
1375 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1376 return -1;
1377 return 0;
1378#elif defined(SPARC) || defined(SPARC64)
1379 state->u_regs[U_REG_G1] = new;
1380 return 0;
1381#elif defined(MIPS)
1382 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1383 return -1;
1384 return 0;
1385#elif defined(ALPHA)
1386 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1387 return -1;
1388 return 0;
1389#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001390 /* setbpt/clearbpt never used: */
1391 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001392#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001393 /* setbpt/clearbpt never used: */
1394 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001395#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001396 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001397 switch (new) {
1398 case 2:
1399 break; /* x86 SYS_fork */
1400 case SYS_clone:
1401 new = 120;
1402 break;
1403 default:
1404 fprintf(stderr, "%s: unexpected syscall %d\n",
1405 __FUNCTION__, new);
1406 return -1;
1407 }
1408 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1409 return -1;
1410 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1411 return -1;
1412 return 0;
1413#elif defined(HPPA)
1414 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1415 return -1;
1416 return 0;
1417#elif defined(SH)
1418 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1419 return -1;
1420 return 0;
1421#elif defined(SH64)
1422 /* Top half of reg encodes the no. of args n as 0x1n.
1423 Assume 0 args as kernel never actually checks... */
1424 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1425 0x100000 | new) < 0)
1426 return -1;
1427 return 0;
1428#elif defined(CRISV10) || defined(CRISV32)
1429 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1430 return -1;
1431 return 0;
1432#elif defined(ARM)
1433 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1434# ifndef PTRACE_SET_SYSCALL
1435# define PTRACE_SET_SYSCALL 23
1436# endif
1437 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1438 return -1;
1439 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001440#elif defined(AARCH64)
1441 /* setbpt/clearbpt never used: */
1442 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001443#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001444 /* setbpt/clearbpt never used: */
1445 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001446#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001447 /* setbpt/clearbpt never used: */
1448 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001449#elif defined(OR1K)
1450 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001451#elif defined(METAG)
1452 /* setbpt/clearbpt never used: */
1453 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001454#elif defined(XTENSA)
1455 /* setbpt/clearbpt never used: */
1456 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301457#elif defined(ARC)
1458 /* setbpt/clearbpt never used: */
1459 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001460#else
1461#warning Do not know how to handle change_syscall for this architecture
1462#endif /* architecture */
1463 return -1;
1464}
1465
Roland McGrathd81f1d92003-01-09 06:53:34 +00001466int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001467setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468{
Roland McGrath3291ef22008-05-20 00:34:34 +00001469 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001470 arg_setup_state state;
1471
1472 if (tcp->flags & TCB_BPTSET) {
1473 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1474 return -1;
1475 }
1476
Roland McGrath3291ef22008-05-20 00:34:34 +00001477 /*
1478 * It's a silly kludge to initialize this with a search at runtime.
1479 * But it's better than maintaining another magic thing in the
1480 * godforsaken tables.
1481 */
1482 if (clone_scno[current_personality] == 0) {
1483 int i;
1484 for (i = 0; i < nsyscalls; ++i)
1485 if (sysent[i].sys_func == sys_clone) {
1486 clone_scno[current_personality] = i;
1487 break;
1488 }
1489 }
1490
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001491 if (tcp->s_ent->sys_func == sys_fork ||
1492 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 if (arg_setup(tcp, &state) < 0
1494 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1495 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001496 || change_syscall(tcp, &state,
1497 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001498 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1499 || set_arg1(tcp, &state, 0) < 0
1500 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001501 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001502 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1503 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001504 tcp->flags |= TCB_BPTSET;
1505 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001506 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001507
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001508 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001509 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001510 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001511 vfork semantics into plain fork - each application must not
1512 depend on the vfork specifics according to POSIX. We would
1513 hang waiting for the parent resume otherwise. We need to
1514 clear also CLONE_VM but only in the CLONE_VFORK case as
1515 otherwise we would break pthread_create. */
1516
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001517 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1518 if (new_arg0 & CLONE_VFORK)
1519 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1520 if (arg_setup(tcp, &state) < 0
1521 || set_arg0(tcp, &state, new_arg0) < 0
1522 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001523 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001524 tcp->inst[0] = tcp->u_arg[arg0_index];
1525 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001526 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001527 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001528 }
1529
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001530 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1531 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001532 return -1;
1533}
1534
1535int
Denys Vlasenko12014262011-05-30 14:00:14 +02001536clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001537{
1538 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001539 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001540 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001541 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1542 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1543 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001544 if (errno != ESRCH)
1545 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001546 tcp->flags &= ~TCB_BPTSET;
1547 return 0;
1548}