blob: 33482d5f501b826784c972e7542b640d51f9420c [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 *
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
Dmitry V. Levin7845a422014-04-17 13:32:47 +0000228printllval(struct tcb *tcp, const char *format, int arg_no, bool align)
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. Levin7845a422014-04-17 13:32:47 +0000239 if (align) {
240 /* Align arg_no to the next even number. */
241 arg_no = (arg_no + 1) & 0xe;
242 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000243# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100244 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
245 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100246 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000247# endif /* SUPPORTED_PERSONALITIES */
248#elif SIZEOF_LONG > 4
249# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
250#elif defined LINUX_MIPSN32
251 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100252 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000253#elif defined X32
254 if (current_personality == 0) {
255 tprintf(format, tcp->ext_arg[arg_no]);
256 arg_no++;
257 } else {
258 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
259 arg_no += 2;
260 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100261#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000262# if defined __ARM_EABI__ || \
263 defined LINUX_MIPSO32 || \
264 defined POWERPC || \
265 defined XTENSA
Dmitry V. Levin7845a422014-04-17 13:32:47 +0000266 if (align) {
267 /* Align arg_no to the next even number. */
268 arg_no = (arg_no + 1) & 0xe;
269 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000270# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100271 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
272 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100273#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000274
Chris Metcalf879dddd2013-03-01 10:41:02 +0100275 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100276}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100277
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000278/*
279 * Interpret `xlat' as an array of flags
280 * print the entries whose bits are on in `flags'
281 * return # of flags printed.
282 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200283void
Denys Vlasenko12014262011-05-30 14:00:14 +0200284addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000285{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200286 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287 if (xlat->val && (flags & xlat->val) == xlat->val) {
288 tprintf("|%s", xlat->str);
289 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290 }
291 }
292 if (flags) {
293 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295}
296
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000297/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200298 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000299 * Print to static string the entries whose bits are on in `flags'
300 * Return static string.
301 */
302const char *
303sprintflags(const char *prefix, const struct xlat *xlat, int flags)
304{
305 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200306 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000307 int found = 0;
308
Denys Vlasenko52845572011-08-31 12:07:38 +0200309 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000310
311 for (; xlat->str; xlat++) {
312 if ((flags & xlat->val) == xlat->val) {
313 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200314 *outptr++ = '|';
315 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000316 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100317 flags &= ~xlat->val;
318 if (!flags)
319 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000320 }
321 }
322 if (flags) {
323 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200324 *outptr++ = '|';
325 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000326 }
327
328 return outstr;
329}
330
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000332printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333{
334 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000335 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336
337 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200338 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339 return 1;
340 }
341
342 sep = "";
343 for (n = 0; xlat->str; xlat++) {
344 if (xlat->val && (flags & xlat->val) == xlat->val) {
345 tprintf("%s%s", sep, xlat->str);
346 flags &= ~xlat->val;
347 sep = "|";
348 n++;
349 }
350 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000351
352 if (n) {
353 if (flags) {
354 tprintf("%s%#x", sep, flags);
355 n++;
356 }
357 } else {
358 if (flags) {
359 tprintf("%#x", flags);
360 if (dflt)
361 tprintf(" /* %s */", dflt);
362 } else {
363 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200364 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000365 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000366 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000367
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000368 return n;
369}
370
371void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000372printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000373{
Roland McGratheb285352003-01-14 09:59:00 +0000374 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375
376 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200377 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000378 return;
379 }
380 if (umove(tcp, addr, &num) < 0) {
381 tprintf("%#lx", addr);
382 return;
383 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200384 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200386 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387}
388
Roland McGrath6bc12202003-11-13 22:32:27 +0000389void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000390printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000391{
392 int num;
393
394 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200395 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000396 return;
397 }
398 if (umove(tcp, addr, &num) < 0) {
399 tprintf("%#lx", addr);
400 return;
401 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200402 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000403 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200404 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000405}
406
407void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300408printfd(struct tcb *tcp, int fd)
409{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100410 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000411
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100412 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
413 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000414 else
415 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300416}
417
418void
Denys Vlasenko12014262011-05-30 14:00:14 +0200419printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000420{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200421 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000422}
423
Dmitry V. Levina501f142008-11-10 23:19:13 +0000424/*
425 * Quote string `instr' of length `size'
426 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200427 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000428 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100429 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200430 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100431 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000432 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400433int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200434string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000435{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000436 const unsigned char *ustr = (const unsigned char *) instr;
437 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200438 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200440 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200441 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200442 size--;
443 eol = '\0';
444 }
445
446 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000447 if (xflag > 1)
448 usehex = 1;
449 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000450 /* Check for presence of symbol which require
451 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000452 for (i = 0; i < size; ++i) {
453 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000454 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200455 if (c == eol)
456 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100457
458 /* Force hex unless c is printable or whitespace */
459 if (c > 0x7e) {
460 usehex = 1;
461 break;
462 }
463 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
464 * They happen to have ASCII codes 9,10,11,12,13.
465 */
466 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000467 usehex = 1;
468 break;
469 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000470 }
471 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000472
473 *s++ = '\"';
474
475 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000476 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000477 for (i = 0; i < size; ++i) {
478 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000479 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200480 if (c == eol)
481 goto asciz_ended;
482 *s++ = '\\';
483 *s++ = 'x';
484 *s++ = "0123456789abcdef"[c >> 4];
485 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000486 }
487 } else {
488 for (i = 0; i < size; ++i) {
489 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000490 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200491 if (c == eol)
492 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000493 switch (c) {
494 case '\"': case '\\':
495 *s++ = '\\';
496 *s++ = c;
497 break;
498 case '\f':
499 *s++ = '\\';
500 *s++ = 'f';
501 break;
502 case '\n':
503 *s++ = '\\';
504 *s++ = 'n';
505 break;
506 case '\r':
507 *s++ = '\\';
508 *s++ = 'r';
509 break;
510 case '\t':
511 *s++ = '\\';
512 *s++ = 't';
513 break;
514 case '\v':
515 *s++ = '\\';
516 *s++ = 'v';
517 break;
518 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100519 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000520 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200521 else {
522 /* Print \octal */
523 *s++ = '\\';
524 if (i + 1 < size
525 && ustr[i + 1] >= '0'
526 && ustr[i + 1] <= '9'
527 ) {
528 /* Print \ooo */
529 *s++ = '0' + (c >> 6);
530 *s++ = '0' + ((c >> 3) & 0x7);
531 } else {
532 /* Print \[[o]o]o */
533 if ((c >> 3) != 0) {
534 if ((c >> 6) != 0)
535 *s++ = '0' + (c >> 6);
536 *s++ = '0' + ((c >> 3) & 0x7);
537 }
538 }
539 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000540 }
541 break;
542 }
543 }
544 }
545
546 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000548
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200549 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200550 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200551 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
552 * but next char is NUL.
553 */
554 return 0;
555 }
556
557 return 1;
558
559 asciz_ended:
560 *s++ = '\"';
561 *s = '\0';
562 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
563 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564}
565
Dmitry V. Levina501f142008-11-10 23:19:13 +0000566/*
567 * Print path string specified by address `addr' and length `n'.
568 * If path length exceeds `n', append `...' to the output.
569 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000571printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100573 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100574 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100575
Dmitry V. Levina501f142008-11-10 23:19:13 +0000576 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200577 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000578 return;
579 }
580
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100581 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000582 if (n > sizeof path - 1)
583 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000584
585 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100586 nul_seen = umovestr(tcp, addr, n + 1, path);
587 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 tprintf("%#lx", addr);
589 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100590 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000591
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100592 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100593 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100594 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100595 string_quote(path, outstr, -1, n);
596 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100597 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100598 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599 }
600}
601
602void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000603printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000604{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100605 /* Size must correspond to char path[] size in printpathn */
606 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000607}
608
Dmitry V. Levina501f142008-11-10 23:19:13 +0000609/*
610 * Print string specified by address `addr' and length `len'.
611 * If `len' < 0, treat the string as a NUL-terminated string.
612 * If string length exceeds `max_strlen', append `...' to the output.
613 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000614void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200615printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000616{
617 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000619 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100620 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000621
622 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200623 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624 return;
625 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000626 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200627 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000628 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
629
630 if (outstr_size / 4 != max_strlen)
631 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000632 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200633 if (!str)
634 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000635 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200636 if (!outstr)
637 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000638 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000639
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200640 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000641 /*
642 * Treat as a NUL-terminated string: fetch one byte more
643 * because string_quote() quotes one byte less.
644 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000645 size = max_strlen + 1;
646 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647 tprintf("%#lx", addr);
648 return;
649 }
650 }
651 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200652 size = max_strlen;
653 if (size > (unsigned long)len)
654 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000655 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656 tprintf("%#lx", addr);
657 return;
658 }
659 }
660
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100661 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
662 * or we were requested to print more than -s NUM chars)...
663 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100664 ellipsis = (string_quote(str, outstr, len, size) &&
665 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000666
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100667 tprints(outstr);
668 if (ellipsis)
669 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670}
671
John Hughes1d08dcf2001-07-10 13:48:44 +0000672#if HAVE_SYS_UIO_H
673void
Denys Vlasenko12014262011-05-30 14:00:14 +0200674dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000675{
Denys Vlasenko84703742012-02-25 02:38:52 +0100676#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000677 union {
678 struct { u_int32_t base; u_int32_t len; } *iov32;
679 struct { u_int64_t base; u_int64_t len; } *iov64;
680 } iovu;
681#define iov iovu.iov64
682#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100683 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000684#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100685 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000686#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100687 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000688#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000689 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000690#define sizeof_iov sizeof(*iov)
691#define iov_iov_base(i) iov[i].iov_base
692#define iov_iov_len(i) iov[i].iov_len
693#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000694 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200695 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000696
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200697 size = sizeof_iov * len;
698 /* Assuming no sane program has millions of iovs */
699 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000700 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200701 fprintf(stderr, "Out of memory\n");
702 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000703 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000704 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000705 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000706 /* include the buffer number to make it easy to
707 * match up the trace with the source */
708 tprintf(" * %lu bytes in buffer %d\n",
709 (unsigned long)iov_iov_len(i), i);
710 dumpstr(tcp, (long) iov_iov_base(i),
711 iov_iov_len(i));
712 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000713 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200714 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000715#undef sizeof_iov
716#undef iov_iov_base
717#undef iov_iov_len
718#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000719}
720#endif
721
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722void
Denys Vlasenko12014262011-05-30 14:00:14 +0200723dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724{
725 static int strsize = -1;
726 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727
Denys Vlasenko76325802013-02-22 14:47:39 +0100728 char outbuf[
729 (
730 (sizeof(
731 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
732 "1234567890123456") + /*in case I'm off by few:*/ 4)
733 /*align to 8 to make memset easier:*/ + 7) & -8
734 ];
735 const unsigned char *src;
736 int i;
737
738 memset(outbuf, ' ', sizeof(outbuf));
739
740 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200741 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100742 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200743 if (!str) {
744 strsize = -1;
745 fprintf(stderr, "Out of memory\n");
746 return;
747 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100748 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749 }
750
751 if (umoven(tcp, addr, len, (char *) str) < 0)
752 return;
753
Denys Vlasenko76325802013-02-22 14:47:39 +0100754 /* Space-pad to 16 bytes */
755 i = len;
756 while (i & 0xf)
757 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200758
Denys Vlasenko76325802013-02-22 14:47:39 +0100759 i = 0;
760 src = str;
761 while (i < len) {
762 char *dst = outbuf;
763 /* Hex dump */
764 do {
765 if (i < len) {
766 *dst++ = "0123456789abcdef"[*src >> 4];
767 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768 }
769 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100770 *dst++ = ' ';
771 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100773 dst++; /* space is there by memset */
774 i++;
775 if ((i & 7) == 0)
776 dst++; /* space is there by memset */
777 src++;
778 } while (i & 0xf);
779 /* ASCII dump */
780 i -= 16;
781 src -= 16;
782 do {
783 if (*src >= ' ' && *src < 0x7f)
784 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100786 *dst++ = '.';
787 src++;
788 } while (++i & 0xf);
789 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100790 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 }
792}
793
Mike Frysinger612659e2012-02-14 14:38:28 +0100794#ifdef HAVE_PROCESS_VM_READV
795/* C library supports this, but the kernel might not. */
796static bool process_vm_readv_not_supported = 0;
797#else
798
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100799/* Need to do this since process_vm_readv() is not yet available in libc.
800 * When libc is be updated, only "static bool process_vm_readv_not_supported"
801 * line should remain.
802 */
803#if !defined(__NR_process_vm_readv)
804# if defined(I386)
805# define __NR_process_vm_readv 347
806# elif defined(X86_64)
807# define __NR_process_vm_readv 310
808# elif defined(POWERPC)
809# define __NR_process_vm_readv 351
810# endif
811#endif
812
813#if defined(__NR_process_vm_readv)
814static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400815/* Have to avoid duplicating with the C library headers. */
816static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100817 const struct iovec *lvec,
818 unsigned long liovcnt,
819 const struct iovec *rvec,
820 unsigned long riovcnt,
821 unsigned long flags)
822{
823 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
824}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400825#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100826#else
827static bool process_vm_readv_not_supported = 1;
828# define process_vm_readv(...) (errno = ENOSYS, -1)
829#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100830
831#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100832
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000833#define PAGMASK (~(PAGSIZ - 1))
834/*
835 * move `len' bytes of data from process `pid'
836 * at address `addr' to our space at `laddr'
837 */
838int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000839umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700841 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000842 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000843 union {
844 long val;
845 char x[sizeof(long)];
846 } u;
847
Denys Vlasenko2544f982013-02-19 17:39:56 +0100848#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100849 if (current_wordsize < sizeof(addr))
850 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100851#endif
852
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100853 if (!process_vm_readv_not_supported) {
854 struct iovec local[1], remote[1];
855 int r;
856
857 local[0].iov_base = laddr;
858 remote[0].iov_base = (void*)addr;
859 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000860 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100861 if (r == len)
862 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000863 if (r >= 0) {
864 error_msg("umoven: short read (%d < %d) @0x%lx",
865 r, len, addr);
866 return -1;
867 }
868 switch (errno) {
869 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100870 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000871 break;
872 case ESRCH:
873 /* the process is gone */
874 return -1;
875 case EFAULT: case EIO: case EPERM:
876 /* address space is inaccessible */
877 return -1;
878 default:
879 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100880 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000881 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100882 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100883 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100884
Dmitry V. Levin97005922013-02-26 21:16:22 +0000885 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 if (addr & (sizeof(long) - 1)) {
887 /* addr not a multiple of sizeof(long) */
888 n = addr - (addr & -sizeof(long)); /* residue */
889 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700890 errno = 0;
891 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000892 switch (errno) {
893 case 0:
894 break;
895 case ESRCH: case EINVAL:
896 /* these could be seen if the process is gone */
897 return -1;
898 case EFAULT: case EIO: case EPERM:
899 /* address space is inaccessible */
900 return -1;
901 default:
902 /* all the rest is strange and should be reported */
903 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
904 pid, addr);
905 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700906 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100907 m = MIN(sizeof(long) - n, len);
908 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100909 addr += sizeof(long);
910 laddr += m;
911 nread += m;
912 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 }
914 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700915 errno = 0;
916 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000917 switch (errno) {
918 case 0:
919 break;
920 case ESRCH: case EINVAL:
921 /* these could be seen if the process is gone */
922 return -1;
923 case EFAULT: case EIO: case EPERM:
924 /* address space is inaccessible */
925 if (nread) {
926 perror_msg("umoven: short read (%d < %d) @0x%lx",
927 nread, nread + len, addr - nread);
928 }
929 return -1;
930 default:
931 /* all the rest is strange and should be reported */
932 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
933 pid, addr);
934 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700935 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100936 m = MIN(sizeof(long), len);
937 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100938 addr += sizeof(long);
939 laddr += m;
940 nread += m;
941 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 return 0;
945}
946
947/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100948 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100950 *
951 * Returns < 0 on error, > 0 if NUL was seen,
952 * (TODO if useful: return count of bytes including NUL),
953 * else 0 if len bytes were read but no NUL byte seen.
954 *
955 * Note: there is no guarantee we won't overwrite some bytes
956 * in laddr[] _after_ terminating NUL (but, of course,
957 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 */
959int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000960umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000961{
Denys Vlasenko16940922013-03-01 18:52:59 +0100962#if SIZEOF_LONG == 4
963 const unsigned long x01010101 = 0x01010101ul;
964 const unsigned long x80808080 = 0x80808080ul;
965#elif SIZEOF_LONG == 8
966 const unsigned long x01010101 = 0x0101010101010101ul;
967 const unsigned long x80808080 = 0x8080808080808080ul;
968#else
969# error SIZEOF_LONG > 8
970#endif
971
Roland McGratheb9e2e82009-06-02 16:49:22 -0700972 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100973 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100975 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976 char x[sizeof(long)];
977 } u;
978
Denys Vlasenko2544f982013-02-19 17:39:56 +0100979#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100980 if (current_wordsize < sizeof(addr))
981 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000982#endif
983
Dmitry V. Levin97005922013-02-26 21:16:22 +0000984 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100985 if (!process_vm_readv_not_supported) {
986 struct iovec local[1], remote[1];
987
988 local[0].iov_base = laddr;
989 remote[0].iov_base = (void*)addr;
990
991 while (len > 0) {
992 int end_in_page;
993 int r;
994 int chunk_len;
995
996 /* Don't read kilobytes: most strings are short */
997 chunk_len = len;
998 if (chunk_len > 256)
999 chunk_len = 256;
1000 /* Don't cross pages. I guess otherwise we can get EFAULT
1001 * and fail to notice that terminating NUL lies
1002 * in the existing (first) page.
1003 * (I hope there aren't arches with pages < 4K)
1004 */
1005 end_in_page = ((addr + chunk_len) & 4095);
1006 r = chunk_len - end_in_page;
1007 if (r > 0) /* if chunk_len > end_in_page */
1008 chunk_len = r; /* chunk_len -= end_in_page */
1009
1010 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001011 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1012 if (r > 0) {
1013 if (memchr(local[0].iov_base, '\0', r))
1014 return 1;
1015 local[0].iov_base += r;
1016 remote[0].iov_base += r;
1017 len -= r;
1018 nread += r;
1019 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001020 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001021 switch (errno) {
1022 case ENOSYS:
1023 process_vm_readv_not_supported = 1;
1024 goto vm_readv_didnt_work;
1025 case ESRCH:
1026 /* the process is gone */
1027 return -1;
1028 case EFAULT: case EIO: case EPERM:
1029 /* address space is inaccessible */
1030 if (nread) {
1031 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1032 nread, nread + len, addr);
1033 }
1034 return -1;
1035 default:
1036 /* all the rest is strange and should be reported */
1037 perror_msg("process_vm_readv");
1038 return -1;
1039 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001040 }
1041 return 0;
1042 }
1043 vm_readv_didnt_work:
1044
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 if (addr & (sizeof(long) - 1)) {
1046 /* addr not a multiple of sizeof(long) */
1047 n = addr - (addr & -sizeof(long)); /* residue */
1048 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001049 errno = 0;
1050 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001051 switch (errno) {
1052 case 0:
1053 break;
1054 case ESRCH: case EINVAL:
1055 /* these could be seen if the process is gone */
1056 return -1;
1057 case EFAULT: case EIO: case EPERM:
1058 /* address space is inaccessible */
1059 return -1;
1060 default:
1061 /* all the rest is strange and should be reported */
1062 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1063 pid, addr);
1064 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001065 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001066 m = MIN(sizeof(long) - n, len);
1067 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 while (n & (sizeof(long) - 1))
1069 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001070 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001071 addr += sizeof(long);
1072 laddr += m;
1073 nread += m;
1074 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001076
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001078 errno = 0;
1079 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001080 switch (errno) {
1081 case 0:
1082 break;
1083 case ESRCH: case EINVAL:
1084 /* these could be seen if the process is gone */
1085 return -1;
1086 case EFAULT: case EIO: case EPERM:
1087 /* address space is inaccessible */
1088 if (nread) {
1089 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1090 nread, nread + len, addr - nread);
1091 }
1092 return -1;
1093 default:
1094 /* all the rest is strange and should be reported */
1095 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1096 pid, addr);
1097 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001098 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001099 m = MIN(sizeof(long), len);
1100 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001101 /* "If a NUL char exists in this word" */
1102 if ((u.val - x01010101) & ~u.val & x80808080)
1103 return 1;
1104 addr += sizeof(long);
1105 laddr += m;
1106 nread += m;
1107 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001109 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110}
1111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001113upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114{
1115 long val;
1116
Roland McGratheb9e2e82009-06-02 16:49:22 -07001117 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001118 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001119 if (val == -1 && errno) {
1120 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001121 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001122 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001124 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 *res = val;
1126 return 0;
1127}
1128
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001129/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1130 * and PTRACE_O_TRACE[V]FORK for tracing children.
1131 * If you are adding a new arch which is only supported by newer kernels,
1132 * you most likely don't need to add any code below
1133 * beside a dummy "return 0" block in change_syscall().
1134 */
1135
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001136/*
1137 * These #if's are huge, please indent them correctly.
1138 * It's easy to get confused otherwise.
1139 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001141#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001142
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001143#ifndef CLONE_PTRACE
1144# define CLONE_PTRACE 0x00002000
1145#endif
1146#ifndef CLONE_VFORK
1147# define CLONE_VFORK 0x00004000
1148#endif
1149#ifndef CLONE_VM
1150# define CLONE_VM 0x00000100
1151#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001152
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001153#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001154
1155typedef unsigned long *arg_setup_state;
1156
1157static int
1158arg_setup(struct tcb *tcp, arg_setup_state *state)
1159{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001160 unsigned long cfm, sof, sol;
1161 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001162
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001163 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001164 /* Satisfy a false GCC warning. */
1165 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001166 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001167 }
Roland McGrath08267b82004-02-20 22:56:43 +00001168
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001169 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001170 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001171 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172 return -1;
1173
1174 sof = (cfm >> 0) & 0x7f;
1175 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001176 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001177
Jan Kratochvil1f942712008-08-06 21:38:52 +00001178 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001179 return 0;
1180}
1181
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001182# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001183
Roland McGrathd81f1d92003-01-09 06:53:34 +00001184static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001185get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001186{
Roland McGrath08267b82004-02-20 22:56:43 +00001187 int ret;
1188
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001189 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001190 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001191 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001192 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001193 (unsigned long) ia64_rse_skip_regs(*state, 0),
1194 sizeof(long), (void *) valp);
1195 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001196}
1197
1198static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001199get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001200{
Roland McGrath08267b82004-02-20 22:56:43 +00001201 int ret;
1202
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001203 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001204 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001205 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001206 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001207 (unsigned long) ia64_rse_skip_regs(*state, 1),
1208 sizeof(long), (void *) valp);
1209 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211
1212static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001213set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214{
Roland McGrath08267b82004-02-20 22:56:43 +00001215 int req = PTRACE_POKEDATA;
1216 void *ap;
1217
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001218 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001219 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1220 req = PTRACE_POKEUSER;
1221 } else
1222 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001223 errno = 0;
1224 ptrace(req, tcp->pid, ap, val);
1225 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226}
1227
1228static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001229set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001230{
Roland McGrath08267b82004-02-20 22:56:43 +00001231 int req = PTRACE_POKEDATA;
1232 void *ap;
1233
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001234 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001235 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1236 req = PTRACE_POKEUSER;
1237 } else
1238 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001239 errno = 0;
1240 ptrace(req, tcp->pid, ap, val);
1241 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001242}
1243
Roland McGrathb659f872008-07-18 01:19:36 +00001244/* ia64 does not return the input arguments from functions (and syscalls)
1245 according to ia64 RSE (Register Stack Engine) behavior. */
1246
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001247# define restore_arg0(tcp, state, val) ((void) (state), 0)
1248# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001249
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001250#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001251
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001252# if defined(SPARC64)
1253# undef PTRACE_GETREGS
1254# define PTRACE_GETREGS PTRACE_GETREGS64
1255# undef PTRACE_SETREGS
1256# define PTRACE_SETREGS PTRACE_SETREGS64
1257# endif
1258
Mike Frysinger8566c502009-10-12 11:05:14 -04001259typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001260
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001261# define arg_setup(tcp, state) \
1262 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1263# define arg_finish_change(tcp, state) \
1264 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001266# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1267# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1268# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1269# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1270# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001272#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001274# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001275/* Note: this is only true for the `clone' system call, which handles
1276 arguments specially. We could as well say that its first two arguments
1277 are swapped relative to other architectures, but that would just be
1278 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001279# define arg0_offset PT_GPR3
1280# define arg1_offset PT_ORIGGPR2
1281# define restore_arg0(tcp, state, val) ((void) (state), 0)
1282# define restore_arg1(tcp, state, val) ((void) (state), 0)
1283# define arg0_index 1
1284# define arg1_index 0
1285# elif defined(ALPHA) || defined(MIPS)
1286# define arg0_offset REG_A0
1287# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001288# elif defined(POWERPC)
1289# define arg0_offset (sizeof(unsigned long)*PT_R3)
1290# define arg1_offset (sizeof(unsigned long)*PT_R4)
1291# define restore_arg0(tcp, state, val) ((void) (state), 0)
1292# elif defined(HPPA)
1293# define arg0_offset PT_GR26
1294# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001295# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001296# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1297# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1298# elif defined(SH)
1299# define arg0_offset (4*(REG_REG0+4))
1300# define arg1_offset (4*(REG_REG0+5))
1301# elif defined(SH64)
1302 /* ABI defines arg0 & 1 in r2 & r3 */
1303# define arg0_offset (REG_OFFSET+16)
1304# define arg1_offset (REG_OFFSET+24)
1305# define restore_arg0(tcp, state, val) 0
1306# elif defined CRISV10 || defined CRISV32
1307# define arg0_offset (4*PT_R11)
1308# define arg1_offset (4*PT_ORIG_R10)
1309# define restore_arg0(tcp, state, val) 0
1310# define restore_arg1(tcp, state, val) 0
1311# define arg0_index 1
1312# define arg1_index 0
1313# else
1314# define arg0_offset 0
1315# define arg1_offset 4
1316# if defined ARM
1317# define restore_arg0(tcp, state, val) 0
1318# endif
1319# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001320
1321typedef int arg_setup_state;
1322
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001323# define arg_setup(tcp, state) (0)
1324# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001325# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1326# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327
1328static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001329set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001331 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332}
1333
1334static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001335set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001337 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338}
1339
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001340#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001341
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001342#ifndef restore_arg0
1343# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1344#endif
1345#ifndef restore_arg1
1346# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1347#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001349#ifndef arg0_index
1350# define arg0_index 0
1351# define arg1_index 1
1352#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001353
James Hogan05eb9052012-11-29 17:37:37 +00001354static int
1355change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1356{
1357#if defined(I386)
1358 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1359 return -1;
1360 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001361#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001362 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1363 return -1;
1364 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001365#elif defined(X32)
1366 /* setbpt/clearbpt never used: */
1367 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001368#elif defined(POWERPC)
1369 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1370 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1371 return -1;
1372 return 0;
1373#elif defined(S390) || defined(S390X)
1374 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1375 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1376 return -1;
1377 return 0;
1378#elif defined(M68K)
1379 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1380 return -1;
1381 return 0;
1382#elif defined(SPARC) || defined(SPARC64)
1383 state->u_regs[U_REG_G1] = new;
1384 return 0;
1385#elif defined(MIPS)
1386 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1387 return -1;
1388 return 0;
1389#elif defined(ALPHA)
1390 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1391 return -1;
1392 return 0;
1393#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001394 /* setbpt/clearbpt never used: */
1395 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001396#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001397 /* setbpt/clearbpt never used: */
1398 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001399#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001400 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001401 switch (new) {
1402 case 2:
1403 break; /* x86 SYS_fork */
1404 case SYS_clone:
1405 new = 120;
1406 break;
1407 default:
1408 fprintf(stderr, "%s: unexpected syscall %d\n",
1409 __FUNCTION__, new);
1410 return -1;
1411 }
1412 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1413 return -1;
1414 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1415 return -1;
1416 return 0;
1417#elif defined(HPPA)
1418 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1419 return -1;
1420 return 0;
1421#elif defined(SH)
1422 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1423 return -1;
1424 return 0;
1425#elif defined(SH64)
1426 /* Top half of reg encodes the no. of args n as 0x1n.
1427 Assume 0 args as kernel never actually checks... */
1428 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1429 0x100000 | new) < 0)
1430 return -1;
1431 return 0;
1432#elif defined(CRISV10) || defined(CRISV32)
1433 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1434 return -1;
1435 return 0;
1436#elif defined(ARM)
1437 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1438# ifndef PTRACE_SET_SYSCALL
1439# define PTRACE_SET_SYSCALL 23
1440# endif
1441 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1442 return -1;
1443 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001444#elif defined(AARCH64)
1445 /* setbpt/clearbpt never used: */
1446 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001447#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001448 /* setbpt/clearbpt never used: */
1449 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001450#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001451 /* setbpt/clearbpt never used: */
1452 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001453#elif defined(OR1K)
1454 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001455#elif defined(METAG)
1456 /* setbpt/clearbpt never used: */
1457 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001458#elif defined(XTENSA)
1459 /* setbpt/clearbpt never used: */
1460 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301461#elif defined(ARC)
1462 /* setbpt/clearbpt never used: */
1463 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001464#else
1465#warning Do not know how to handle change_syscall for this architecture
1466#endif /* architecture */
1467 return -1;
1468}
1469
Roland McGrathd81f1d92003-01-09 06:53:34 +00001470int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001471setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001472{
Roland McGrath3291ef22008-05-20 00:34:34 +00001473 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001474 arg_setup_state state;
1475
1476 if (tcp->flags & TCB_BPTSET) {
1477 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1478 return -1;
1479 }
1480
Roland McGrath3291ef22008-05-20 00:34:34 +00001481 /*
1482 * It's a silly kludge to initialize this with a search at runtime.
1483 * But it's better than maintaining another magic thing in the
1484 * godforsaken tables.
1485 */
1486 if (clone_scno[current_personality] == 0) {
1487 int i;
1488 for (i = 0; i < nsyscalls; ++i)
1489 if (sysent[i].sys_func == sys_clone) {
1490 clone_scno[current_personality] = i;
1491 break;
1492 }
1493 }
1494
Dmitry V. Levin65563152014-05-12 13:43:10 +00001495 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001496 if (arg_setup(tcp, &state) < 0
1497 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1498 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001499 || change_syscall(tcp, &state,
1500 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001501 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1502 || set_arg1(tcp, &state, 0) < 0
1503 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001504 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001505 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1506 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001507 tcp->flags |= TCB_BPTSET;
1508 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001509 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001510
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001511 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001512 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001513 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001514 vfork semantics into plain fork - each application must not
1515 depend on the vfork specifics according to POSIX. We would
1516 hang waiting for the parent resume otherwise. We need to
1517 clear also CLONE_VM but only in the CLONE_VFORK case as
1518 otherwise we would break pthread_create. */
1519
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001520 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1521 if (new_arg0 & CLONE_VFORK)
1522 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1523 if (arg_setup(tcp, &state) < 0
1524 || set_arg0(tcp, &state, new_arg0) < 0
1525 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001526 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001527 tcp->inst[0] = tcp->u_arg[arg0_index];
1528 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001529 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001530 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001531 }
1532
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001533 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1534 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001535 return -1;
1536}
1537
1538int
Denys Vlasenko12014262011-05-30 14:00:14 +02001539clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001540{
1541 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001542 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001543 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001544 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1545 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1546 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001547 if (errno != ESRCH)
1548 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001549 tcp->flags &= ~TCB_BPTSET;
1550 return 0;
1551}