blob: 72873da59616ab19114b7b78fee7d9fa085f75a6 [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#if HAVE_LONG_LONG
182/*
183 * Print 64bit argument at position llarg and return the index of the next
184 * argument.
185 */
186int
187printllval(struct tcb *tcp, const char *format, int llarg)
188{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100189# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100190 if (current_personality == 0) {
191 tprintf(format, tcp->u_arg[llarg]);
192 llarg++;
193 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200194# ifdef POWERPC64
195 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200196 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200197# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100198 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
199 llarg += 2;
200 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200201# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100202 tprintf(format, tcp->u_arg[llarg]);
203 llarg++;
H.J. Lu35be5812012-04-16 13:00:01 +0200204# elif defined LINUX_MIPSN32 || defined X32
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100205 tprintf(format, tcp->ext_arg[llarg]);
206 llarg++;
207# else
208 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
209 llarg += 2;
210# endif
211 return llarg;
212}
213#endif
214
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215/*
216 * Interpret `xlat' as an array of flags
217 * print the entries whose bits are on in `flags'
218 * return # of flags printed.
219 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200220void
Denys Vlasenko12014262011-05-30 14:00:14 +0200221addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000222{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200223 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000224 if (xlat->val && (flags & xlat->val) == xlat->val) {
225 tprintf("|%s", xlat->str);
226 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227 }
228 }
229 if (flags) {
230 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232}
233
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000234/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200235 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000236 * Print to static string the entries whose bits are on in `flags'
237 * Return static string.
238 */
239const char *
240sprintflags(const char *prefix, const struct xlat *xlat, int flags)
241{
242 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200243 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000244 int found = 0;
245
Denys Vlasenko52845572011-08-31 12:07:38 +0200246 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000247
248 for (; xlat->str; xlat++) {
249 if ((flags & xlat->val) == xlat->val) {
250 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200251 *outptr++ = '|';
252 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100254 flags &= ~xlat->val;
255 if (!flags)
256 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000257 }
258 }
259 if (flags) {
260 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200261 *outptr++ = '|';
262 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000263 }
264
265 return outstr;
266}
267
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000269printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270{
271 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000272 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000273
274 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200275 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000276 return 1;
277 }
278
279 sep = "";
280 for (n = 0; xlat->str; xlat++) {
281 if (xlat->val && (flags & xlat->val) == xlat->val) {
282 tprintf("%s%s", sep, xlat->str);
283 flags &= ~xlat->val;
284 sep = "|";
285 n++;
286 }
287 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000288
289 if (n) {
290 if (flags) {
291 tprintf("%s%#x", sep, flags);
292 n++;
293 }
294 } else {
295 if (flags) {
296 tprintf("%#x", flags);
297 if (dflt)
298 tprintf(" /* %s */", dflt);
299 } else {
300 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200301 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000302 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000303 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000304
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000305 return n;
306}
307
308void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000309printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310{
Roland McGratheb285352003-01-14 09:59:00 +0000311 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312
313 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200314 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000315 return;
316 }
317 if (umove(tcp, addr, &num) < 0) {
318 tprintf("%#lx", addr);
319 return;
320 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200321 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200323 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324}
325
Roland McGrath6bc12202003-11-13 22:32:27 +0000326void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000327printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000328{
329 int num;
330
331 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200332 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000333 return;
334 }
335 if (umove(tcp, addr, &num) < 0) {
336 tprintf("%#lx", addr);
337 return;
338 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200339 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000340 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200341 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000342}
343
344void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300345printfd(struct tcb *tcp, int fd)
346{
Grant Edwards8a082772011-04-07 20:25:40 +0000347 const char *p;
348
349 if (show_fd_path && (p = getfdpath(tcp, fd)))
350 tprintf("%d<%s>", fd, p);
351 else
352 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300353}
354
355void
Denys Vlasenko12014262011-05-30 14:00:14 +0200356printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000357{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200358 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000359}
360
Dmitry V. Levina501f142008-11-10 23:19:13 +0000361/*
362 * Quote string `instr' of length `size'
363 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200364 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000365 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100366 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200367 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100368 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000369 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400370int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200371string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000373 const unsigned char *ustr = (const unsigned char *) instr;
374 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200375 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200377 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200378 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200379 size--;
380 eol = '\0';
381 }
382
383 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000384 if (xflag > 1)
385 usehex = 1;
386 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000387 /* Check for presence of symbol which require
388 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000389 for (i = 0; i < size; ++i) {
390 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000391 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200392 if (c == eol)
393 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000394 if (!isprint(c) && !isspace(c)) {
395 usehex = 1;
396 break;
397 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000398 }
399 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000400
401 *s++ = '\"';
402
403 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000404 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000405 for (i = 0; i < size; ++i) {
406 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000407 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200408 if (c == eol)
409 goto asciz_ended;
410 *s++ = '\\';
411 *s++ = 'x';
412 *s++ = "0123456789abcdef"[c >> 4];
413 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000414 }
415 } else {
416 for (i = 0; i < size; ++i) {
417 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000418 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200419 if (c == eol)
420 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000421 switch (c) {
422 case '\"': case '\\':
423 *s++ = '\\';
424 *s++ = c;
425 break;
426 case '\f':
427 *s++ = '\\';
428 *s++ = 'f';
429 break;
430 case '\n':
431 *s++ = '\\';
432 *s++ = 'n';
433 break;
434 case '\r':
435 *s++ = '\\';
436 *s++ = 'r';
437 break;
438 case '\t':
439 *s++ = '\\';
440 *s++ = 't';
441 break;
442 case '\v':
443 *s++ = '\\';
444 *s++ = 'v';
445 break;
446 default:
447 if (isprint(c))
448 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200449 else {
450 /* Print \octal */
451 *s++ = '\\';
452 if (i + 1 < size
453 && ustr[i + 1] >= '0'
454 && ustr[i + 1] <= '9'
455 ) {
456 /* Print \ooo */
457 *s++ = '0' + (c >> 6);
458 *s++ = '0' + ((c >> 3) & 0x7);
459 } else {
460 /* Print \[[o]o]o */
461 if ((c >> 3) != 0) {
462 if ((c >> 6) != 0)
463 *s++ = '0' + (c >> 6);
464 *s++ = '0' + ((c >> 3) & 0x7);
465 }
466 }
467 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000468 }
469 break;
470 }
471 }
472 }
473
474 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000475 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000476
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200477 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200478 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200479 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
480 * but next char is NUL.
481 */
482 return 0;
483 }
484
485 return 1;
486
487 asciz_ended:
488 *s++ = '\"';
489 *s = '\0';
490 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
491 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000492}
493
Dmitry V. Levina501f142008-11-10 23:19:13 +0000494/*
495 * Print path string specified by address `addr' and length `n'.
496 * If path length exceeds `n', append `...' to the output.
497 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000499printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000500{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100501 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100502 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100503
Dmitry V. Levina501f142008-11-10 23:19:13 +0000504 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200505 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000506 return;
507 }
508
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100509 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000510 if (n > sizeof path - 1)
511 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000512
513 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100514 nul_seen = umovestr(tcp, addr, n + 1, path);
515 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 tprintf("%#lx", addr);
517 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100518 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000519
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100520 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100521 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100522 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100523 string_quote(path, outstr, -1, n);
524 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100525 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100526 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527 }
528}
529
530void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000531printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100533 /* Size must correspond to char path[] size in printpathn */
534 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000535}
536
Dmitry V. Levina501f142008-11-10 23:19:13 +0000537/*
538 * Print string specified by address `addr' and length `len'.
539 * If `len' < 0, treat the string as a NUL-terminated string.
540 * If string length exceeds `max_strlen', append `...' to the output.
541 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000542void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200543printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000544{
545 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000546 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000547 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100548 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000549
550 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200551 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552 return;
553 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000554 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200555 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000556 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
557
558 if (outstr_size / 4 != max_strlen)
559 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000560 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200561 if (!str)
562 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000563 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200564 if (!outstr)
565 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200568 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569 /*
570 * Treat as a NUL-terminated string: fetch one byte more
571 * because string_quote() quotes one byte less.
572 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000573 size = max_strlen + 1;
574 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 tprintf("%#lx", addr);
576 return;
577 }
578 }
579 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200580 size = max_strlen;
581 if (size > (unsigned long)len)
582 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000583 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 tprintf("%#lx", addr);
585 return;
586 }
587 }
588
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100589 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
590 * or we were requested to print more than -s NUM chars)...
591 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100592 ellipsis = (string_quote(str, outstr, len, size) &&
593 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000594
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100595 tprints(outstr);
596 if (ellipsis)
597 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598}
599
John Hughes1d08dcf2001-07-10 13:48:44 +0000600#if HAVE_SYS_UIO_H
601void
Denys Vlasenko12014262011-05-30 14:00:14 +0200602dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000603{
Denys Vlasenko84703742012-02-25 02:38:52 +0100604#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000605 union {
606 struct { u_int32_t base; u_int32_t len; } *iov32;
607 struct { u_int64_t base; u_int64_t len; } *iov64;
608 } iovu;
609#define iov iovu.iov64
610#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100611 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000612#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100613 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000614#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100615 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000616#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000617 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000618#define sizeof_iov sizeof(*iov)
619#define iov_iov_base(i) iov[i].iov_base
620#define iov_iov_len(i) iov[i].iov_len
621#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000622 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200623 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000624
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200625 size = sizeof_iov * len;
626 /* Assuming no sane program has millions of iovs */
627 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000628 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200629 fprintf(stderr, "Out of memory\n");
630 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000631 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000632 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000633 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000634 /* include the buffer number to make it easy to
635 * match up the trace with the source */
636 tprintf(" * %lu bytes in buffer %d\n",
637 (unsigned long)iov_iov_len(i), i);
638 dumpstr(tcp, (long) iov_iov_base(i),
639 iov_iov_len(i));
640 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000641 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200642 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000643#undef sizeof_iov
644#undef iov_iov_base
645#undef iov_iov_len
646#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000647}
648#endif
649
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000650void
Denys Vlasenko12014262011-05-30 14:00:14 +0200651dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652{
653 static int strsize = -1;
654 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 char *s;
656 int i, j;
657
658 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200659 free(str);
660 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200661 if (!str) {
662 strsize = -1;
663 fprintf(stderr, "Out of memory\n");
664 return;
665 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 strsize = len;
667 }
668
669 if (umoven(tcp, addr, len, (char *) str) < 0)
670 return;
671
672 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200673 char outstr[80];
674
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675 s = outstr;
676 sprintf(s, " | %05x ", i);
677 s += 9;
678 for (j = 0; j < 16; j++) {
679 if (j == 8)
680 *s++ = ' ';
681 if (i + j < len) {
682 sprintf(s, " %02x", str[i + j]);
683 s += 3;
684 }
685 else {
686 *s++ = ' '; *s++ = ' '; *s++ = ' ';
687 }
688 }
689 *s++ = ' '; *s++ = ' ';
690 for (j = 0; j < 16; j++) {
691 if (j == 8)
692 *s++ = ' ';
693 if (i + j < len) {
694 if (isprint(str[i + j]))
695 *s++ = str[i + j];
696 else
697 *s++ = '.';
698 }
699 else
700 *s++ = ' ';
701 }
702 tprintf("%s |\n", outstr);
703 }
704}
705
Mike Frysinger612659e2012-02-14 14:38:28 +0100706#ifdef HAVE_PROCESS_VM_READV
707/* C library supports this, but the kernel might not. */
708static bool process_vm_readv_not_supported = 0;
709#else
710
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100711/* Need to do this since process_vm_readv() is not yet available in libc.
712 * When libc is be updated, only "static bool process_vm_readv_not_supported"
713 * line should remain.
714 */
715#if !defined(__NR_process_vm_readv)
716# if defined(I386)
717# define __NR_process_vm_readv 347
718# elif defined(X86_64)
719# define __NR_process_vm_readv 310
720# elif defined(POWERPC)
721# define __NR_process_vm_readv 351
722# endif
723#endif
724
725#if defined(__NR_process_vm_readv)
726static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400727/* Have to avoid duplicating with the C library headers. */
728static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100729 const struct iovec *lvec,
730 unsigned long liovcnt,
731 const struct iovec *rvec,
732 unsigned long riovcnt,
733 unsigned long flags)
734{
735 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
736}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400737#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100738#else
739static bool process_vm_readv_not_supported = 1;
740# define process_vm_readv(...) (errno = ENOSYS, -1)
741#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100742
743#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100744
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745#define PAGMASK (~(PAGSIZ - 1))
746/*
747 * move `len' bytes of data from process `pid'
748 * at address `addr' to our space at `laddr'
749 */
750int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000751umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700753 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000754 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100755 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 union {
757 long val;
758 char x[sizeof(long)];
759 } u;
760
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100761#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100762 if (current_wordsize < sizeof(addr))
763 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100764#endif
765
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100766 if (!process_vm_readv_not_supported) {
767 struct iovec local[1], remote[1];
768 int r;
769
770 local[0].iov_base = laddr;
771 remote[0].iov_base = (void*)addr;
772 local[0].iov_len = remote[0].iov_len = len;
773 r = process_vm_readv(pid,
774 local, 1,
775 remote, 1,
776 /*flags:*/ 0
777 );
778 if (r < 0) {
779 if (errno == ENOSYS)
780 process_vm_readv_not_supported = 1;
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000781 else if (errno != EINVAL && errno != ESRCH)
782 /* EINVAL or ESRCH could be seen if process is gone,
783 * all the rest is strange and should be reported. */
784 perror_msg("%s", "process_vm_readv");
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100785 goto vm_readv_didnt_work;
786 }
787 return r;
788 }
789 vm_readv_didnt_work:
790
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100791 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 if (addr & (sizeof(long) - 1)) {
793 /* addr not a multiple of sizeof(long) */
794 n = addr - (addr & -sizeof(long)); /* residue */
795 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700796 errno = 0;
797 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
798 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700799 /* But if not started, we had a bogus address. */
800 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100801 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700802 return -1;
803 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000804 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100805 m = MIN(sizeof(long) - n, len);
806 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 addr += sizeof(long), laddr += m, len -= m;
808 }
809 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700810 errno = 0;
811 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
812 if (errno) {
813 if (started && (errno==EPERM || errno==EIO)) {
814 /* Ran into 'end of memory' - stupid "printpath" */
815 return 0;
816 }
817 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100818 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700819 return -1;
820 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000821 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100822 m = MIN(sizeof(long), len);
823 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000824 addr += sizeof(long), laddr += m, len -= m;
825 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000827 return 0;
828}
829
830/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100831 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100833 *
834 * Returns < 0 on error, > 0 if NUL was seen,
835 * (TODO if useful: return count of bytes including NUL),
836 * else 0 if len bytes were read but no NUL byte seen.
837 *
838 * Note: there is no guarantee we won't overwrite some bytes
839 * in laddr[] _after_ terminating NUL (but, of course,
840 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000841 */
842int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000843umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000844{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100845 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700846 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 int i, n, m;
848 union {
849 long val;
850 char x[sizeof(long)];
851 } u;
852
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000853#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100854 if (current_wordsize < sizeof(addr))
855 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000856#endif
857
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100858 if (!process_vm_readv_not_supported) {
859 struct iovec local[1], remote[1];
860
861 local[0].iov_base = laddr;
862 remote[0].iov_base = (void*)addr;
863
864 while (len > 0) {
865 int end_in_page;
866 int r;
867 int chunk_len;
868
869 /* Don't read kilobytes: most strings are short */
870 chunk_len = len;
871 if (chunk_len > 256)
872 chunk_len = 256;
873 /* Don't cross pages. I guess otherwise we can get EFAULT
874 * and fail to notice that terminating NUL lies
875 * in the existing (first) page.
876 * (I hope there aren't arches with pages < 4K)
877 */
878 end_in_page = ((addr + chunk_len) & 4095);
879 r = chunk_len - end_in_page;
880 if (r > 0) /* if chunk_len > end_in_page */
881 chunk_len = r; /* chunk_len -= end_in_page */
882
883 local[0].iov_len = remote[0].iov_len = chunk_len;
884 r = process_vm_readv(pid,
885 local, 1,
886 remote, 1,
887 /*flags:*/ 0
888 );
889 if (r < 0) {
890 if (errno == ENOSYS)
891 process_vm_readv_not_supported = 1;
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000892 else if (errno != EINVAL && errno != ESRCH)
893 /* EINVAL or ESRCH could be seen
894 * if process is gone, all the rest
895 * is strange and should be reported. */
896 perror_msg("%s", "process_vm_readv");
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100897 goto vm_readv_didnt_work;
898 }
899 if (memchr(local[0].iov_base, '\0', r))
900 return 1;
901 local[0].iov_base += r;
902 remote[0].iov_base += r;
903 len -= r;
904 }
905 return 0;
906 }
907 vm_readv_didnt_work:
908
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100909 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 if (addr & (sizeof(long) - 1)) {
911 /* addr not a multiple of sizeof(long) */
912 n = addr - (addr & -sizeof(long)); /* residue */
913 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700914 errno = 0;
915 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
916 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700917 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100918 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700919 return -1;
920 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000921 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100922 m = MIN(sizeof(long) - n, len);
923 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924 while (n & (sizeof(long) - 1))
925 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100926 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 addr += sizeof(long), laddr += m, len -= m;
928 }
929 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700930 errno = 0;
931 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
932 if (errno) {
933 if (started && (errno==EPERM || errno==EIO)) {
934 /* Ran into 'end of memory' - stupid "printpath" */
935 return 0;
936 }
937 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100938 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700939 return -1;
940 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000941 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100942 m = MIN(sizeof(long), len);
943 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 for (i = 0; i < sizeof(long); i++)
945 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100946 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 addr += sizeof(long), laddr += m, len -= m;
948 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000949 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950}
951
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952int
Denys Vlasenko12014262011-05-30 14:00:14 +0200953upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954{
955 long val;
956
Roland McGratheb9e2e82009-06-02 16:49:22 -0700957 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100958 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700959 if (val == -1 && errno) {
960 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100961 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700962 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700964 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 *res = val;
966 return 0;
967}
968
Denys Vlasenkod27809c2013-02-12 12:50:10 +0100969/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
970 * and PTRACE_O_TRACE[V]FORK for tracing children.
971 * If you are adding a new arch which is only supported by newer kernels,
972 * you most likely don't need to add any code below
973 * beside a dummy "return 0" block in change_syscall().
974 */
975
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000976/*
977 * These #if's are huge, please indent them correctly.
978 * It's easy to get confused otherwise.
979 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100981#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +0000982
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100983#ifndef CLONE_PTRACE
984# define CLONE_PTRACE 0x00002000
985#endif
986#ifndef CLONE_VFORK
987# define CLONE_VFORK 0x00004000
988#endif
989#ifndef CLONE_VM
990# define CLONE_VM 0x00000100
991#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +0000992
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100993#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +0000994
995typedef unsigned long *arg_setup_state;
996
997static int
998arg_setup(struct tcb *tcp, arg_setup_state *state)
999{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001000 unsigned long cfm, sof, sol;
1001 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001002
Jan Kratochvil1f942712008-08-06 21:38:52 +00001003 if (ia32) {
1004 /* Satisfy a false GCC warning. */
1005 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001006 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001007 }
Roland McGrath08267b82004-02-20 22:56:43 +00001008
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001009 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001010 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001011 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001012 return -1;
1013
1014 sof = (cfm >> 0) & 0x7f;
1015 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001016 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001017
Jan Kratochvil1f942712008-08-06 21:38:52 +00001018 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001019 return 0;
1020}
1021
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001022# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001023
Roland McGrathd81f1d92003-01-09 06:53:34 +00001024static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001025get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001026{
Roland McGrath08267b82004-02-20 22:56:43 +00001027 int ret;
1028
1029 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001030 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001031 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001032 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001033 (unsigned long) ia64_rse_skip_regs(*state, 0),
1034 sizeof(long), (void *) valp);
1035 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001036}
1037
1038static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001039get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001040{
Roland McGrath08267b82004-02-20 22:56:43 +00001041 int ret;
1042
1043 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001044 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001045 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001046 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001047 (unsigned long) ia64_rse_skip_regs(*state, 1),
1048 sizeof(long), (void *) valp);
1049 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001050}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001051
1052static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001053set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001054{
Roland McGrath08267b82004-02-20 22:56:43 +00001055 int req = PTRACE_POKEDATA;
1056 void *ap;
1057
1058 if (ia32) {
1059 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1060 req = PTRACE_POKEUSER;
1061 } else
1062 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001063 errno = 0;
1064 ptrace(req, tcp->pid, ap, val);
1065 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001066}
1067
1068static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001069set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001070{
Roland McGrath08267b82004-02-20 22:56:43 +00001071 int req = PTRACE_POKEDATA;
1072 void *ap;
1073
1074 if (ia32) {
1075 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1076 req = PTRACE_POKEUSER;
1077 } else
1078 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001079 errno = 0;
1080 ptrace(req, tcp->pid, ap, val);
1081 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001082}
1083
Roland McGrathb659f872008-07-18 01:19:36 +00001084/* ia64 does not return the input arguments from functions (and syscalls)
1085 according to ia64 RSE (Register Stack Engine) behavior. */
1086
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001087# define restore_arg0(tcp, state, val) ((void) (state), 0)
1088# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001089
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001090#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001091
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001092# if defined(SPARC64)
1093# undef PTRACE_GETREGS
1094# define PTRACE_GETREGS PTRACE_GETREGS64
1095# undef PTRACE_SETREGS
1096# define PTRACE_SETREGS PTRACE_SETREGS64
1097# endif
1098
Mike Frysinger8566c502009-10-12 11:05:14 -04001099typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001100
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001101# define arg_setup(tcp, state) \
1102 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1103# define arg_finish_change(tcp, state) \
1104 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001105
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001106# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1107# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1108# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1109# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1110# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001111
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001112#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001113
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001114# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001115/* Note: this is only true for the `clone' system call, which handles
1116 arguments specially. We could as well say that its first two arguments
1117 are swapped relative to other architectures, but that would just be
1118 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001119# define arg0_offset PT_GPR3
1120# define arg1_offset PT_ORIGGPR2
1121# define restore_arg0(tcp, state, val) ((void) (state), 0)
1122# define restore_arg1(tcp, state, val) ((void) (state), 0)
1123# define arg0_index 1
1124# define arg1_index 0
1125# elif defined(ALPHA) || defined(MIPS)
1126# define arg0_offset REG_A0
1127# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001128# elif defined(POWERPC)
1129# define arg0_offset (sizeof(unsigned long)*PT_R3)
1130# define arg1_offset (sizeof(unsigned long)*PT_R4)
1131# define restore_arg0(tcp, state, val) ((void) (state), 0)
1132# elif defined(HPPA)
1133# define arg0_offset PT_GR26
1134# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001135# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001136# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1137# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1138# elif defined(SH)
1139# define arg0_offset (4*(REG_REG0+4))
1140# define arg1_offset (4*(REG_REG0+5))
1141# elif defined(SH64)
1142 /* ABI defines arg0 & 1 in r2 & r3 */
1143# define arg0_offset (REG_OFFSET+16)
1144# define arg1_offset (REG_OFFSET+24)
1145# define restore_arg0(tcp, state, val) 0
1146# elif defined CRISV10 || defined CRISV32
1147# define arg0_offset (4*PT_R11)
1148# define arg1_offset (4*PT_ORIG_R10)
1149# define restore_arg0(tcp, state, val) 0
1150# define restore_arg1(tcp, state, val) 0
1151# define arg0_index 1
1152# define arg1_index 0
1153# else
1154# define arg0_offset 0
1155# define arg1_offset 4
1156# if defined ARM
1157# define restore_arg0(tcp, state, val) 0
1158# endif
1159# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001160
1161typedef int arg_setup_state;
1162
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001163# define arg_setup(tcp, state) (0)
1164# define arg_finish_change(tcp, state) 0
1165# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1166# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001167
1168static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001169set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001170{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001171 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172}
1173
1174static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001175set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001176{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001177 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001178}
1179
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001180#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001181
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001182#ifndef restore_arg0
1183# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1184#endif
1185#ifndef restore_arg1
1186# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1187#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001188
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001189#ifndef arg0_index
1190# define arg0_index 0
1191# define arg1_index 1
1192#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001193
James Hogan05eb9052012-11-29 17:37:37 +00001194static int
1195change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1196{
1197#if defined(I386)
1198 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1199 return -1;
1200 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001201#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001202 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1203 return -1;
1204 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001205#elif defined(X32)
1206 /* setbpt/clearbpt never used: */
1207 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001208#elif defined(POWERPC)
1209 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1210 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1211 return -1;
1212 return 0;
1213#elif defined(S390) || defined(S390X)
1214 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1215 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1216 return -1;
1217 return 0;
1218#elif defined(M68K)
1219 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1220 return -1;
1221 return 0;
1222#elif defined(SPARC) || defined(SPARC64)
1223 state->u_regs[U_REG_G1] = new;
1224 return 0;
1225#elif defined(MIPS)
1226 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1227 return -1;
1228 return 0;
1229#elif defined(ALPHA)
1230 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1231 return -1;
1232 return 0;
1233#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001234 /* setbpt/clearbpt never used: */
1235 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001236#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001237 /* setbpt/clearbpt never used: */
1238 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001239#elif defined(IA64)
1240 if (ia32) {
1241 switch (new) {
1242 case 2:
1243 break; /* x86 SYS_fork */
1244 case SYS_clone:
1245 new = 120;
1246 break;
1247 default:
1248 fprintf(stderr, "%s: unexpected syscall %d\n",
1249 __FUNCTION__, new);
1250 return -1;
1251 }
1252 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1253 return -1;
1254 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1255 return -1;
1256 return 0;
1257#elif defined(HPPA)
1258 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1259 return -1;
1260 return 0;
1261#elif defined(SH)
1262 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1263 return -1;
1264 return 0;
1265#elif defined(SH64)
1266 /* Top half of reg encodes the no. of args n as 0x1n.
1267 Assume 0 args as kernel never actually checks... */
1268 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1269 0x100000 | new) < 0)
1270 return -1;
1271 return 0;
1272#elif defined(CRISV10) || defined(CRISV32)
1273 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1274 return -1;
1275 return 0;
1276#elif defined(ARM)
1277 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1278# ifndef PTRACE_SET_SYSCALL
1279# define PTRACE_SET_SYSCALL 23
1280# endif
1281 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1282 return -1;
1283 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001284#elif defined(AARCH64)
1285 /* setbpt/clearbpt never used: */
1286 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001287#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001288 /* setbpt/clearbpt never used: */
1289 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001290#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001291 /* setbpt/clearbpt never used: */
1292 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001293#elif defined(OR1K)
1294 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan05eb9052012-11-29 17:37:37 +00001295#else
1296#warning Do not know how to handle change_syscall for this architecture
1297#endif /* architecture */
1298 return -1;
1299}
1300
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001302setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303{
Roland McGrath3291ef22008-05-20 00:34:34 +00001304 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001305 arg_setup_state state;
1306
1307 if (tcp->flags & TCB_BPTSET) {
1308 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1309 return -1;
1310 }
1311
Roland McGrath3291ef22008-05-20 00:34:34 +00001312 /*
1313 * It's a silly kludge to initialize this with a search at runtime.
1314 * But it's better than maintaining another magic thing in the
1315 * godforsaken tables.
1316 */
1317 if (clone_scno[current_personality] == 0) {
1318 int i;
1319 for (i = 0; i < nsyscalls; ++i)
1320 if (sysent[i].sys_func == sys_clone) {
1321 clone_scno[current_personality] = i;
1322 break;
1323 }
1324 }
1325
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001326 if (sysent[tcp->scno].sys_func == sys_fork ||
1327 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001328 if (arg_setup(tcp, &state) < 0
1329 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1330 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001331 || change_syscall(tcp, &state,
1332 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001333 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1334 || set_arg1(tcp, &state, 0) < 0
1335 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001337 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1338 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339 tcp->flags |= TCB_BPTSET;
1340 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001341 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001343 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001344 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001345 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001346 vfork semantics into plain fork - each application must not
1347 depend on the vfork specifics according to POSIX. We would
1348 hang waiting for the parent resume otherwise. We need to
1349 clear also CLONE_VM but only in the CLONE_VFORK case as
1350 otherwise we would break pthread_create. */
1351
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001352 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1353 if (new_arg0 & CLONE_VFORK)
1354 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1355 if (arg_setup(tcp, &state) < 0
1356 || set_arg0(tcp, &state, new_arg0) < 0
1357 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001358 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001359 tcp->inst[0] = tcp->u_arg[arg0_index];
1360 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001361 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001362 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001363 }
1364
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001365 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1366 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001367 return -1;
1368}
1369
1370int
Denys Vlasenko12014262011-05-30 14:00:14 +02001371clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001372{
1373 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001374 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001375 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001376 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1377 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1378 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001379 if (errno != ESRCH)
1380 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001381 tcp->flags &= ~TCB_BPTSET;
1382 return 0;
1383}