blob: e00c9a6496ff8bbe135d51939455a25703d38aed [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 Akkerman76baf7c1999-02-19 00:21:36 +000049# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010051# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010058# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000059# undef ia64_fpreg
60# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000061#endif
62
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063/* macros */
64#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010065# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000066#endif
67#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010068# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000072string_to_uint(const char *str)
73{
74 char *error;
75 long value;
76
77 if (!*str)
78 return -1;
79 errno = 0;
80 value = strtol(str, &error, 10);
81 if (errno || *error || value < 0 || (long)(int)value != value)
82 return -1;
83 return (int)value;
84}
85
86int
Denys Vlasenko12014262011-05-30 14:00:14 +020087tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088{
89 return a->tv_sec || a->tv_usec;
90}
91
92int
Denys Vlasenko12014262011-05-30 14:00:14 +020093tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094{
95 if (a->tv_sec < b->tv_sec
96 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
97 return -1;
98 if (a->tv_sec > b->tv_sec
99 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
100 return 1;
101 return 0;
102}
103
104double
Denys Vlasenko12014262011-05-30 14:00:14 +0200105tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106{
107 return tv->tv_sec + tv->tv_usec/1000000.0;
108}
109
110void
Denys Vlasenko12014262011-05-30 14:00:14 +0200111tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112{
113 tv->tv_sec = a->tv_sec + b->tv_sec;
114 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000115 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116 tv->tv_sec++;
117 tv->tv_usec -= 1000000;
118 }
119}
120
121void
Denys Vlasenko12014262011-05-30 14:00:14 +0200122tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123{
124 tv->tv_sec = a->tv_sec - b->tv_sec;
125 tv->tv_usec = a->tv_usec - b->tv_usec;
126 if (((long) tv->tv_usec) < 0) {
127 tv->tv_sec--;
128 tv->tv_usec += 1000000;
129 }
130}
131
132void
Denys Vlasenko12014262011-05-30 14:00:14 +0200133tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134{
135 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
136 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
137 tv->tv_usec %= 1000000;
138}
139
140void
Denys Vlasenko12014262011-05-30 14:00:14 +0200141tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142{
143 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000144 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145 tv->tv_usec %= 1000000;
146}
147
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000148const char *
149xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150{
151 for (; xlat->str != NULL; xlat++)
152 if (xlat->val == val)
153 return xlat->str;
154 return NULL;
155}
156
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200157#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200158char *
159stpcpy(char *dst, const char *src)
160{
161 while ((*dst = *src++) != '\0')
162 dst++;
163 return dst;
164}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200165#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200166
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167/*
168 * Print entry in struct xlat table, if there.
169 */
170void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000171printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000173 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200176 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177 else
178 tprintf("%#x /* %s */", val, dflt);
179}
180
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100181/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100182 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100183 * argument.
184 */
185int
Chris Metcalf879dddd2013-03-01 10:41:02 +0100186printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100187{
Andreas Schwab341d09a2013-03-30 22:31:56 +0100188#if defined(X86_64) || defined(POWERPC64) || defined(TILE) || defined(AARCH64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100189 if (current_personality == 0) {
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100190 /* Technically, format expects "long long",
191 * but we supply "long". We expect that
192 * on this arch, they are the same.
193 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100194 tprintf(format, tcp->u_arg[arg_no]);
195 arg_no++;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100196 } else {
Chris Metcalf879dddd2013-03-01 10:41:02 +0100197# if defined(POWERPC64)
198 /* Align arg_no to next even number */
199 arg_no = (arg_no + 1) & 0xe;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100200# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100201 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
202 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100203 }
Mike Frysinger6303f352013-04-30 23:48:07 -0400204#elif defined IA64 || defined ALPHA || defined S390X
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100205 /* Technically, format expects "long long",
206 * but we supply "long". We expect that
207 * on this arch, they are the same.
208 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100209 tprintf(format, tcp->u_arg[arg_no]);
210 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000211#elif defined X32
212 if (current_personality == 0) {
213 tprintf(format, tcp->ext_arg[arg_no]);
214 arg_no++;
215 } else {
216 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
217 arg_no += 2;
218 }
219#elif defined LINUX_MIPSN32
Chris Metcalf879dddd2013-03-01 10:41:02 +0100220 tprintf(format, tcp->ext_arg[arg_no]);
221 arg_no++;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100222#else
223# if SIZEOF_LONG > 4
224# error BUG: must not combine two args for long long on this arch
225# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100226 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
227 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100228#endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100229 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100230}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100231
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232/*
233 * Interpret `xlat' as an array of flags
234 * print the entries whose bits are on in `flags'
235 * return # of flags printed.
236 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200237void
Denys Vlasenko12014262011-05-30 14:00:14 +0200238addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000239{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200240 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241 if (xlat->val && (flags & xlat->val) == xlat->val) {
242 tprintf("|%s", xlat->str);
243 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 }
245 }
246 if (flags) {
247 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249}
250
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000251/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200252 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253 * Print to static string the entries whose bits are on in `flags'
254 * Return static string.
255 */
256const char *
257sprintflags(const char *prefix, const struct xlat *xlat, int flags)
258{
259 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200260 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000261 int found = 0;
262
Denys Vlasenko52845572011-08-31 12:07:38 +0200263 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000264
265 for (; xlat->str; xlat++) {
266 if ((flags & xlat->val) == xlat->val) {
267 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200268 *outptr++ = '|';
269 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000270 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100271 flags &= ~xlat->val;
272 if (!flags)
273 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000274 }
275 }
276 if (flags) {
277 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200278 *outptr++ = '|';
279 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000280 }
281
282 return outstr;
283}
284
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000285int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000286printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287{
288 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000289 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290
291 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200292 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293 return 1;
294 }
295
296 sep = "";
297 for (n = 0; xlat->str; xlat++) {
298 if (xlat->val && (flags & xlat->val) == xlat->val) {
299 tprintf("%s%s", sep, xlat->str);
300 flags &= ~xlat->val;
301 sep = "|";
302 n++;
303 }
304 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000305
306 if (n) {
307 if (flags) {
308 tprintf("%s%#x", sep, flags);
309 n++;
310 }
311 } else {
312 if (flags) {
313 tprintf("%#x", flags);
314 if (dflt)
315 tprintf(" /* %s */", dflt);
316 } else {
317 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200318 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000319 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000320 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000321
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322 return n;
323}
324
325void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000326printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327{
Roland McGratheb285352003-01-14 09:59:00 +0000328 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000329
330 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200331 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000332 return;
333 }
334 if (umove(tcp, addr, &num) < 0) {
335 tprintf("%#lx", addr);
336 return;
337 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200338 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200340 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000341}
342
Roland McGrath6bc12202003-11-13 22:32:27 +0000343void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000344printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000345{
346 int num;
347
348 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200349 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000350 return;
351 }
352 if (umove(tcp, addr, &num) < 0) {
353 tprintf("%#lx", addr);
354 return;
355 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200356 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000357 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200358 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000359}
360
361void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300362printfd(struct tcb *tcp, int fd)
363{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100364 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000365
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100366 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
367 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000368 else
369 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300370}
371
372void
Denys Vlasenko12014262011-05-30 14:00:14 +0200373printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000374{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200375 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000376}
377
Dmitry V. Levina501f142008-11-10 23:19:13 +0000378/*
379 * Quote string `instr' of length `size'
380 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200381 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000382 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100383 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200384 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100385 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000386 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400387int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200388string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000390 const unsigned char *ustr = (const unsigned char *) instr;
391 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200392 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200394 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200395 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200396 size--;
397 eol = '\0';
398 }
399
400 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000401 if (xflag > 1)
402 usehex = 1;
403 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000404 /* Check for presence of symbol which require
405 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000406 for (i = 0; i < size; ++i) {
407 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000408 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200409 if (c == eol)
410 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100411
412 /* Force hex unless c is printable or whitespace */
413 if (c > 0x7e) {
414 usehex = 1;
415 break;
416 }
417 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
418 * They happen to have ASCII codes 9,10,11,12,13.
419 */
420 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000421 usehex = 1;
422 break;
423 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000424 }
425 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000426
427 *s++ = '\"';
428
429 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000430 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000431 for (i = 0; i < size; ++i) {
432 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000433 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200434 if (c == eol)
435 goto asciz_ended;
436 *s++ = '\\';
437 *s++ = 'x';
438 *s++ = "0123456789abcdef"[c >> 4];
439 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000440 }
441 } else {
442 for (i = 0; i < size; ++i) {
443 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000444 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200445 if (c == eol)
446 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000447 switch (c) {
448 case '\"': case '\\':
449 *s++ = '\\';
450 *s++ = c;
451 break;
452 case '\f':
453 *s++ = '\\';
454 *s++ = 'f';
455 break;
456 case '\n':
457 *s++ = '\\';
458 *s++ = 'n';
459 break;
460 case '\r':
461 *s++ = '\\';
462 *s++ = 'r';
463 break;
464 case '\t':
465 *s++ = '\\';
466 *s++ = 't';
467 break;
468 case '\v':
469 *s++ = '\\';
470 *s++ = 'v';
471 break;
472 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100473 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000474 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200475 else {
476 /* Print \octal */
477 *s++ = '\\';
478 if (i + 1 < size
479 && ustr[i + 1] >= '0'
480 && ustr[i + 1] <= '9'
481 ) {
482 /* Print \ooo */
483 *s++ = '0' + (c >> 6);
484 *s++ = '0' + ((c >> 3) & 0x7);
485 } else {
486 /* Print \[[o]o]o */
487 if ((c >> 3) != 0) {
488 if ((c >> 6) != 0)
489 *s++ = '0' + (c >> 6);
490 *s++ = '0' + ((c >> 3) & 0x7);
491 }
492 }
493 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000494 }
495 break;
496 }
497 }
498 }
499
500 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000502
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200503 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200504 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200505 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
506 * but next char is NUL.
507 */
508 return 0;
509 }
510
511 return 1;
512
513 asciz_ended:
514 *s++ = '\"';
515 *s = '\0';
516 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
517 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518}
519
Dmitry V. Levina501f142008-11-10 23:19:13 +0000520/*
521 * Print path string specified by address `addr' and length `n'.
522 * If path length exceeds `n', append `...' to the output.
523 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000525printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100527 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100528 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100529
Dmitry V. Levina501f142008-11-10 23:19:13 +0000530 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200531 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000532 return;
533 }
534
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100535 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000536 if (n > sizeof path - 1)
537 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000538
539 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100540 nul_seen = umovestr(tcp, addr, n + 1, path);
541 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 tprintf("%#lx", addr);
543 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100544 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000545
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100546 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100547 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100548 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100549 string_quote(path, outstr, -1, n);
550 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100551 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100552 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553 }
554}
555
556void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000557printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100559 /* Size must correspond to char path[] size in printpathn */
560 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000561}
562
Dmitry V. Levina501f142008-11-10 23:19:13 +0000563/*
564 * Print string specified by address `addr' and length `len'.
565 * If `len' < 0, treat the string as a NUL-terminated string.
566 * If string length exceeds `max_strlen', append `...' to the output.
567 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000568void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200569printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000570{
571 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000573 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100574 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575
576 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200577 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578 return;
579 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000580 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200581 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000582 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
583
584 if (outstr_size / 4 != max_strlen)
585 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000586 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200587 if (!str)
588 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000589 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200590 if (!outstr)
591 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000593
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200594 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000595 /*
596 * Treat as a NUL-terminated string: fetch one byte more
597 * because string_quote() quotes one byte less.
598 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000599 size = max_strlen + 1;
600 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601 tprintf("%#lx", addr);
602 return;
603 }
604 }
605 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200606 size = max_strlen;
607 if (size > (unsigned long)len)
608 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000609 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000610 tprintf("%#lx", addr);
611 return;
612 }
613 }
614
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100615 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
616 * or we were requested to print more than -s NUM chars)...
617 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100618 ellipsis = (string_quote(str, outstr, len, size) &&
619 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000620
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100621 tprints(outstr);
622 if (ellipsis)
623 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624}
625
John Hughes1d08dcf2001-07-10 13:48:44 +0000626#if HAVE_SYS_UIO_H
627void
Denys Vlasenko12014262011-05-30 14:00:14 +0200628dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000629{
Denys Vlasenko84703742012-02-25 02:38:52 +0100630#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000631 union {
632 struct { u_int32_t base; u_int32_t len; } *iov32;
633 struct { u_int64_t base; u_int64_t len; } *iov64;
634 } iovu;
635#define iov iovu.iov64
636#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100637 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000638#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100639 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000640#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100641 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000642#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000643 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000644#define sizeof_iov sizeof(*iov)
645#define iov_iov_base(i) iov[i].iov_base
646#define iov_iov_len(i) iov[i].iov_len
647#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000648 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200649 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000650
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200651 size = sizeof_iov * len;
652 /* Assuming no sane program has millions of iovs */
653 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000654 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200655 fprintf(stderr, "Out of memory\n");
656 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000657 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000658 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000659 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000660 /* include the buffer number to make it easy to
661 * match up the trace with the source */
662 tprintf(" * %lu bytes in buffer %d\n",
663 (unsigned long)iov_iov_len(i), i);
664 dumpstr(tcp, (long) iov_iov_base(i),
665 iov_iov_len(i));
666 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000667 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200668 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000669#undef sizeof_iov
670#undef iov_iov_base
671#undef iov_iov_len
672#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000673}
674#endif
675
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676void
Denys Vlasenko12014262011-05-30 14:00:14 +0200677dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678{
679 static int strsize = -1;
680 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681
Denys Vlasenko76325802013-02-22 14:47:39 +0100682 char outbuf[
683 (
684 (sizeof(
685 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
686 "1234567890123456") + /*in case I'm off by few:*/ 4)
687 /*align to 8 to make memset easier:*/ + 7) & -8
688 ];
689 const unsigned char *src;
690 int i;
691
692 memset(outbuf, ' ', sizeof(outbuf));
693
694 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200695 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100696 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200697 if (!str) {
698 strsize = -1;
699 fprintf(stderr, "Out of memory\n");
700 return;
701 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100702 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 }
704
705 if (umoven(tcp, addr, len, (char *) str) < 0)
706 return;
707
Denys Vlasenko76325802013-02-22 14:47:39 +0100708 /* Space-pad to 16 bytes */
709 i = len;
710 while (i & 0xf)
711 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200712
Denys Vlasenko76325802013-02-22 14:47:39 +0100713 i = 0;
714 src = str;
715 while (i < len) {
716 char *dst = outbuf;
717 /* Hex dump */
718 do {
719 if (i < len) {
720 *dst++ = "0123456789abcdef"[*src >> 4];
721 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 }
723 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100724 *dst++ = ' ';
725 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100727 dst++; /* space is there by memset */
728 i++;
729 if ((i & 7) == 0)
730 dst++; /* space is there by memset */
731 src++;
732 } while (i & 0xf);
733 /* ASCII dump */
734 i -= 16;
735 src -= 16;
736 do {
737 if (*src >= ' ' && *src < 0x7f)
738 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000739 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100740 *dst++ = '.';
741 src++;
742 } while (++i & 0xf);
743 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100744 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745 }
746}
747
Mike Frysinger612659e2012-02-14 14:38:28 +0100748#ifdef HAVE_PROCESS_VM_READV
749/* C library supports this, but the kernel might not. */
750static bool process_vm_readv_not_supported = 0;
751#else
752
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100753/* Need to do this since process_vm_readv() is not yet available in libc.
754 * When libc is be updated, only "static bool process_vm_readv_not_supported"
755 * line should remain.
756 */
757#if !defined(__NR_process_vm_readv)
758# if defined(I386)
759# define __NR_process_vm_readv 347
760# elif defined(X86_64)
761# define __NR_process_vm_readv 310
762# elif defined(POWERPC)
763# define __NR_process_vm_readv 351
764# endif
765#endif
766
767#if defined(__NR_process_vm_readv)
768static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400769/* Have to avoid duplicating with the C library headers. */
770static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100771 const struct iovec *lvec,
772 unsigned long liovcnt,
773 const struct iovec *rvec,
774 unsigned long riovcnt,
775 unsigned long flags)
776{
777 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
778}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400779#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100780#else
781static bool process_vm_readv_not_supported = 1;
782# define process_vm_readv(...) (errno = ENOSYS, -1)
783#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100784
785#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100786
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787#define PAGMASK (~(PAGSIZ - 1))
788/*
789 * move `len' bytes of data from process `pid'
790 * at address `addr' to our space at `laddr'
791 */
792int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000793umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700795 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000796 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 union {
798 long val;
799 char x[sizeof(long)];
800 } u;
801
Denys Vlasenko2544f982013-02-19 17:39:56 +0100802#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100803 if (current_wordsize < sizeof(addr))
804 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100805#endif
806
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100807 if (!process_vm_readv_not_supported) {
808 struct iovec local[1], remote[1];
809 int r;
810
811 local[0].iov_base = laddr;
812 remote[0].iov_base = (void*)addr;
813 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000814 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100815 if (r == len)
816 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000817 if (r >= 0) {
818 error_msg("umoven: short read (%d < %d) @0x%lx",
819 r, len, addr);
820 return -1;
821 }
822 switch (errno) {
823 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100824 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000825 break;
826 case ESRCH:
827 /* the process is gone */
828 return -1;
829 case EFAULT: case EIO: case EPERM:
830 /* address space is inaccessible */
831 return -1;
832 default:
833 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100834 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000835 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100836 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100837 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100838
Dmitry V. Levin97005922013-02-26 21:16:22 +0000839 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 if (addr & (sizeof(long) - 1)) {
841 /* addr not a multiple of sizeof(long) */
842 n = addr - (addr & -sizeof(long)); /* residue */
843 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700844 errno = 0;
845 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000846 switch (errno) {
847 case 0:
848 break;
849 case ESRCH: case EINVAL:
850 /* these could be seen if the process is gone */
851 return -1;
852 case EFAULT: case EIO: case EPERM:
853 /* address space is inaccessible */
854 return -1;
855 default:
856 /* all the rest is strange and should be reported */
857 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
858 pid, addr);
859 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700860 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100861 m = MIN(sizeof(long) - n, len);
862 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100863 addr += sizeof(long);
864 laddr += m;
865 nread += m;
866 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867 }
868 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700869 errno = 0;
870 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000871 switch (errno) {
872 case 0:
873 break;
874 case ESRCH: case EINVAL:
875 /* these could be seen if the process is gone */
876 return -1;
877 case EFAULT: case EIO: case EPERM:
878 /* address space is inaccessible */
879 if (nread) {
880 perror_msg("umoven: short read (%d < %d) @0x%lx",
881 nread, nread + len, addr - nread);
882 }
883 return -1;
884 default:
885 /* all the rest is strange and should be reported */
886 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
887 pid, addr);
888 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700889 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100890 m = MIN(sizeof(long), len);
891 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100892 addr += sizeof(long);
893 laddr += m;
894 nread += m;
895 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898 return 0;
899}
900
901/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100902 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100904 *
905 * Returns < 0 on error, > 0 if NUL was seen,
906 * (TODO if useful: return count of bytes including NUL),
907 * else 0 if len bytes were read but no NUL byte seen.
908 *
909 * Note: there is no guarantee we won't overwrite some bytes
910 * in laddr[] _after_ terminating NUL (but, of course,
911 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 */
913int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000914umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915{
Denys Vlasenko16940922013-03-01 18:52:59 +0100916#if SIZEOF_LONG == 4
917 const unsigned long x01010101 = 0x01010101ul;
918 const unsigned long x80808080 = 0x80808080ul;
919#elif SIZEOF_LONG == 8
920 const unsigned long x01010101 = 0x0101010101010101ul;
921 const unsigned long x80808080 = 0x8080808080808080ul;
922#else
923# error SIZEOF_LONG > 8
924#endif
925
Roland McGratheb9e2e82009-06-02 16:49:22 -0700926 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100927 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100929 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000930 char x[sizeof(long)];
931 } u;
932
Denys Vlasenko2544f982013-02-19 17:39:56 +0100933#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100934 if (current_wordsize < sizeof(addr))
935 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000936#endif
937
Dmitry V. Levin97005922013-02-26 21:16:22 +0000938 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100939 if (!process_vm_readv_not_supported) {
940 struct iovec local[1], remote[1];
941
942 local[0].iov_base = laddr;
943 remote[0].iov_base = (void*)addr;
944
945 while (len > 0) {
946 int end_in_page;
947 int r;
948 int chunk_len;
949
950 /* Don't read kilobytes: most strings are short */
951 chunk_len = len;
952 if (chunk_len > 256)
953 chunk_len = 256;
954 /* Don't cross pages. I guess otherwise we can get EFAULT
955 * and fail to notice that terminating NUL lies
956 * in the existing (first) page.
957 * (I hope there aren't arches with pages < 4K)
958 */
959 end_in_page = ((addr + chunk_len) & 4095);
960 r = chunk_len - end_in_page;
961 if (r > 0) /* if chunk_len > end_in_page */
962 chunk_len = r; /* chunk_len -= end_in_page */
963
964 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000965 r = process_vm_readv(pid, local, 1, remote, 1, 0);
966 if (r > 0) {
967 if (memchr(local[0].iov_base, '\0', r))
968 return 1;
969 local[0].iov_base += r;
970 remote[0].iov_base += r;
971 len -= r;
972 nread += r;
973 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100974 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000975 switch (errno) {
976 case ENOSYS:
977 process_vm_readv_not_supported = 1;
978 goto vm_readv_didnt_work;
979 case ESRCH:
980 /* the process is gone */
981 return -1;
982 case EFAULT: case EIO: case EPERM:
983 /* address space is inaccessible */
984 if (nread) {
985 perror_msg("umovestr: short read (%d < %d) @0x%lx",
986 nread, nread + len, addr);
987 }
988 return -1;
989 default:
990 /* all the rest is strange and should be reported */
991 perror_msg("process_vm_readv");
992 return -1;
993 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100994 }
995 return 0;
996 }
997 vm_readv_didnt_work:
998
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 if (addr & (sizeof(long) - 1)) {
1000 /* addr not a multiple of sizeof(long) */
1001 n = addr - (addr & -sizeof(long)); /* residue */
1002 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001003 errno = 0;
1004 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001005 switch (errno) {
1006 case 0:
1007 break;
1008 case ESRCH: case EINVAL:
1009 /* these could be seen if the process is gone */
1010 return -1;
1011 case EFAULT: case EIO: case EPERM:
1012 /* address space is inaccessible */
1013 return -1;
1014 default:
1015 /* all the rest is strange and should be reported */
1016 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1017 pid, addr);
1018 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001019 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001020 m = MIN(sizeof(long) - n, len);
1021 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 while (n & (sizeof(long) - 1))
1023 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001024 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001025 addr += sizeof(long);
1026 laddr += m;
1027 nread += m;
1028 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001030
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001032 errno = 0;
1033 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001034 switch (errno) {
1035 case 0:
1036 break;
1037 case ESRCH: case EINVAL:
1038 /* these could be seen if the process is gone */
1039 return -1;
1040 case EFAULT: case EIO: case EPERM:
1041 /* address space is inaccessible */
1042 if (nread) {
1043 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1044 nread, nread + len, addr - nread);
1045 }
1046 return -1;
1047 default:
1048 /* all the rest is strange and should be reported */
1049 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1050 pid, addr);
1051 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001052 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001053 m = MIN(sizeof(long), len);
1054 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001055 /* "If a NUL char exists in this word" */
1056 if ((u.val - x01010101) & ~u.val & x80808080)
1057 return 1;
1058 addr += sizeof(long);
1059 laddr += m;
1060 nread += m;
1061 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001063 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064}
1065
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066int
Denys Vlasenko12014262011-05-30 14:00:14 +02001067upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068{
1069 long val;
1070
Roland McGratheb9e2e82009-06-02 16:49:22 -07001071 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +01001072 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001073 if (val == -1 && errno) {
1074 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001075 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001076 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001078 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 *res = val;
1080 return 0;
1081}
1082
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001083/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1084 * and PTRACE_O_TRACE[V]FORK for tracing children.
1085 * If you are adding a new arch which is only supported by newer kernels,
1086 * you most likely don't need to add any code below
1087 * beside a dummy "return 0" block in change_syscall().
1088 */
1089
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001090/*
1091 * These #if's are huge, please indent them correctly.
1092 * It's easy to get confused otherwise.
1093 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001094
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001095#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001096
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001097#ifndef CLONE_PTRACE
1098# define CLONE_PTRACE 0x00002000
1099#endif
1100#ifndef CLONE_VFORK
1101# define CLONE_VFORK 0x00004000
1102#endif
1103#ifndef CLONE_VM
1104# define CLONE_VM 0x00000100
1105#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001106
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001107#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001108
1109typedef unsigned long *arg_setup_state;
1110
1111static int
1112arg_setup(struct tcb *tcp, arg_setup_state *state)
1113{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001114 unsigned long cfm, sof, sol;
1115 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001116
Jan Kratochvil1f942712008-08-06 21:38:52 +00001117 if (ia32) {
1118 /* Satisfy a false GCC warning. */
1119 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001120 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001121 }
Roland McGrath08267b82004-02-20 22:56:43 +00001122
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001123 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001124 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001125 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001126 return -1;
1127
1128 sof = (cfm >> 0) & 0x7f;
1129 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001130 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001131
Jan Kratochvil1f942712008-08-06 21:38:52 +00001132 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001133 return 0;
1134}
1135
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001136# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001137
Roland McGrathd81f1d92003-01-09 06:53:34 +00001138static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001139get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001140{
Roland McGrath08267b82004-02-20 22:56:43 +00001141 int ret;
1142
1143 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001144 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001145 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001146 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001147 (unsigned long) ia64_rse_skip_regs(*state, 0),
1148 sizeof(long), (void *) valp);
1149 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001150}
1151
1152static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001153get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001154{
Roland McGrath08267b82004-02-20 22:56:43 +00001155 int ret;
1156
1157 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001158 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001159 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001160 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001161 (unsigned long) ia64_rse_skip_regs(*state, 1),
1162 sizeof(long), (void *) valp);
1163 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001164}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001165
1166static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001167set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001168{
Roland McGrath08267b82004-02-20 22:56:43 +00001169 int req = PTRACE_POKEDATA;
1170 void *ap;
1171
1172 if (ia32) {
1173 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1174 req = PTRACE_POKEUSER;
1175 } else
1176 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001177 errno = 0;
1178 ptrace(req, tcp->pid, ap, val);
1179 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180}
1181
1182static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001183set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001184{
Roland McGrath08267b82004-02-20 22:56:43 +00001185 int req = PTRACE_POKEDATA;
1186 void *ap;
1187
1188 if (ia32) {
1189 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1190 req = PTRACE_POKEUSER;
1191 } else
1192 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001193 errno = 0;
1194 ptrace(req, tcp->pid, ap, val);
1195 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001196}
1197
Roland McGrathb659f872008-07-18 01:19:36 +00001198/* ia64 does not return the input arguments from functions (and syscalls)
1199 according to ia64 RSE (Register Stack Engine) behavior. */
1200
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001201# define restore_arg0(tcp, state, val) ((void) (state), 0)
1202# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001203
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001204#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001205
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001206# if defined(SPARC64)
1207# undef PTRACE_GETREGS
1208# define PTRACE_GETREGS PTRACE_GETREGS64
1209# undef PTRACE_SETREGS
1210# define PTRACE_SETREGS PTRACE_SETREGS64
1211# endif
1212
Mike Frysinger8566c502009-10-12 11:05:14 -04001213typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001215# define arg_setup(tcp, state) \
1216 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1217# define arg_finish_change(tcp, state) \
1218 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001219
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001220# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1221# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1222# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1223# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1224# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001225
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001226#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001227
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001228# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001229/* Note: this is only true for the `clone' system call, which handles
1230 arguments specially. We could as well say that its first two arguments
1231 are swapped relative to other architectures, but that would just be
1232 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001233# define arg0_offset PT_GPR3
1234# define arg1_offset PT_ORIGGPR2
1235# define restore_arg0(tcp, state, val) ((void) (state), 0)
1236# define restore_arg1(tcp, state, val) ((void) (state), 0)
1237# define arg0_index 1
1238# define arg1_index 0
1239# elif defined(ALPHA) || defined(MIPS)
1240# define arg0_offset REG_A0
1241# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001242# elif defined(POWERPC)
1243# define arg0_offset (sizeof(unsigned long)*PT_R3)
1244# define arg1_offset (sizeof(unsigned long)*PT_R4)
1245# define restore_arg0(tcp, state, val) ((void) (state), 0)
1246# elif defined(HPPA)
1247# define arg0_offset PT_GR26
1248# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001249# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001250# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1251# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1252# elif defined(SH)
1253# define arg0_offset (4*(REG_REG0+4))
1254# define arg1_offset (4*(REG_REG0+5))
1255# elif defined(SH64)
1256 /* ABI defines arg0 & 1 in r2 & r3 */
1257# define arg0_offset (REG_OFFSET+16)
1258# define arg1_offset (REG_OFFSET+24)
1259# define restore_arg0(tcp, state, val) 0
1260# elif defined CRISV10 || defined CRISV32
1261# define arg0_offset (4*PT_R11)
1262# define arg1_offset (4*PT_ORIG_R10)
1263# define restore_arg0(tcp, state, val) 0
1264# define restore_arg1(tcp, state, val) 0
1265# define arg0_index 1
1266# define arg1_index 0
1267# else
1268# define arg0_offset 0
1269# define arg1_offset 4
1270# if defined ARM
1271# define restore_arg0(tcp, state, val) 0
1272# endif
1273# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001274
1275typedef int arg_setup_state;
1276
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001277# define arg_setup(tcp, state) (0)
1278# define arg_finish_change(tcp, state) 0
1279# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1280# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281
1282static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001283set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001285 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286}
1287
1288static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001289set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001291 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292}
1293
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001294#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001296#ifndef restore_arg0
1297# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1298#endif
1299#ifndef restore_arg1
1300# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1301#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001302
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001303#ifndef arg0_index
1304# define arg0_index 0
1305# define arg1_index 1
1306#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001307
James Hogan05eb9052012-11-29 17:37:37 +00001308static int
1309change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1310{
1311#if defined(I386)
1312 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1313 return -1;
1314 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001315#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001316 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1317 return -1;
1318 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001319#elif defined(X32)
1320 /* setbpt/clearbpt never used: */
1321 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001322#elif defined(POWERPC)
1323 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1324 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1325 return -1;
1326 return 0;
1327#elif defined(S390) || defined(S390X)
1328 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1329 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1330 return -1;
1331 return 0;
1332#elif defined(M68K)
1333 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1334 return -1;
1335 return 0;
1336#elif defined(SPARC) || defined(SPARC64)
1337 state->u_regs[U_REG_G1] = new;
1338 return 0;
1339#elif defined(MIPS)
1340 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1341 return -1;
1342 return 0;
1343#elif defined(ALPHA)
1344 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1345 return -1;
1346 return 0;
1347#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001348 /* setbpt/clearbpt never used: */
1349 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001350#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001351 /* setbpt/clearbpt never used: */
1352 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001353#elif defined(IA64)
1354 if (ia32) {
1355 switch (new) {
1356 case 2:
1357 break; /* x86 SYS_fork */
1358 case SYS_clone:
1359 new = 120;
1360 break;
1361 default:
1362 fprintf(stderr, "%s: unexpected syscall %d\n",
1363 __FUNCTION__, new);
1364 return -1;
1365 }
1366 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1367 return -1;
1368 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1369 return -1;
1370 return 0;
1371#elif defined(HPPA)
1372 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1373 return -1;
1374 return 0;
1375#elif defined(SH)
1376 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1377 return -1;
1378 return 0;
1379#elif defined(SH64)
1380 /* Top half of reg encodes the no. of args n as 0x1n.
1381 Assume 0 args as kernel never actually checks... */
1382 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1383 0x100000 | new) < 0)
1384 return -1;
1385 return 0;
1386#elif defined(CRISV10) || defined(CRISV32)
1387 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1388 return -1;
1389 return 0;
1390#elif defined(ARM)
1391 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1392# ifndef PTRACE_SET_SYSCALL
1393# define PTRACE_SET_SYSCALL 23
1394# endif
1395 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1396 return -1;
1397 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001398#elif defined(AARCH64)
1399 /* setbpt/clearbpt never used: */
1400 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001401#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001402 /* setbpt/clearbpt never used: */
1403 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001404#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001405 /* setbpt/clearbpt never used: */
1406 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001407#elif defined(OR1K)
1408 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001409#elif defined(METAG)
1410 /* setbpt/clearbpt never used: */
1411 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001412#elif defined(XTENSA)
1413 /* setbpt/clearbpt never used: */
1414 /* Xtensa is only supported since linux 2.6.13 */
James Hogan05eb9052012-11-29 17:37:37 +00001415#else
1416#warning Do not know how to handle change_syscall for this architecture
1417#endif /* architecture */
1418 return -1;
1419}
1420
Roland McGrathd81f1d92003-01-09 06:53:34 +00001421int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001422setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423{
Roland McGrath3291ef22008-05-20 00:34:34 +00001424 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001425 arg_setup_state state;
1426
1427 if (tcp->flags & TCB_BPTSET) {
1428 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1429 return -1;
1430 }
1431
Roland McGrath3291ef22008-05-20 00:34:34 +00001432 /*
1433 * It's a silly kludge to initialize this with a search at runtime.
1434 * But it's better than maintaining another magic thing in the
1435 * godforsaken tables.
1436 */
1437 if (clone_scno[current_personality] == 0) {
1438 int i;
1439 for (i = 0; i < nsyscalls; ++i)
1440 if (sysent[i].sys_func == sys_clone) {
1441 clone_scno[current_personality] = i;
1442 break;
1443 }
1444 }
1445
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001446 if (tcp->s_ent->sys_func == sys_fork ||
1447 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001448 if (arg_setup(tcp, &state) < 0
1449 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1450 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001451 || change_syscall(tcp, &state,
1452 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001453 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1454 || set_arg1(tcp, &state, 0) < 0
1455 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001456 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001457 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1458 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001459 tcp->flags |= TCB_BPTSET;
1460 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001461 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001463 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001464 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001465 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001466 vfork semantics into plain fork - each application must not
1467 depend on the vfork specifics according to POSIX. We would
1468 hang waiting for the parent resume otherwise. We need to
1469 clear also CLONE_VM but only in the CLONE_VFORK case as
1470 otherwise we would break pthread_create. */
1471
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001472 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1473 if (new_arg0 & CLONE_VFORK)
1474 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1475 if (arg_setup(tcp, &state) < 0
1476 || set_arg0(tcp, &state, new_arg0) < 0
1477 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001478 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001479 tcp->inst[0] = tcp->u_arg[arg0_index];
1480 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001481 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001482 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483 }
1484
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001485 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1486 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001487 return -1;
1488}
1489
1490int
Denys Vlasenko12014262011-05-30 14:00:14 +02001491clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001492{
1493 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001494 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001495 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001496 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1497 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1498 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001499 if (errno != ESRCH)
1500 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001501 tcp->flags &= ~TCB_BPTSET;
1502 return 0;
1503}