blob: 0212507ca1bfcb4f0cf8a4296beb48a35a11120c [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
John Spencereb54c472012-12-03 00:27:22 +010042#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010043# include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000044#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000045
Denys Vlasenko84703742012-02-25 02:38:52 +010046#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000047# include <asm/ptrace_offsets.h>
48# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000049#endif
50
Wichert Akkerman36915a11999-07-13 15:45:02 +000051#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010052# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000053# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000054#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010055# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000056# ifdef HAVE_STRUCT_IA64_FPREG
57# define ia64_fpreg XXX_ia64_fpreg
58# endif
59# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
60# define pt_all_user_regs XXX_pt_all_user_regs
61# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010062# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000063# undef ia64_fpreg
64# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000065#endif
66
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000067/* macros */
68#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010069# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#endif
71#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010072# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#endif
74
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000075int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000076string_to_uint(const char *str)
77{
78 char *error;
79 long value;
80
81 if (!*str)
82 return -1;
83 errno = 0;
84 value = strtol(str, &error, 10);
85 if (errno || *error || value < 0 || (long)(int)value != value)
86 return -1;
87 return (int)value;
88}
89
90int
Denys Vlasenko12014262011-05-30 14:00:14 +020091tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092{
93 return a->tv_sec || a->tv_usec;
94}
95
96int
Denys Vlasenko12014262011-05-30 14:00:14 +020097tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098{
99 if (a->tv_sec < b->tv_sec
100 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
101 return -1;
102 if (a->tv_sec > b->tv_sec
103 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
104 return 1;
105 return 0;
106}
107
108double
Denys Vlasenko12014262011-05-30 14:00:14 +0200109tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110{
111 return tv->tv_sec + tv->tv_usec/1000000.0;
112}
113
114void
Denys Vlasenko12014262011-05-30 14:00:14 +0200115tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116{
117 tv->tv_sec = a->tv_sec + b->tv_sec;
118 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000119 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 tv->tv_sec++;
121 tv->tv_usec -= 1000000;
122 }
123}
124
125void
Denys Vlasenko12014262011-05-30 14:00:14 +0200126tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127{
128 tv->tv_sec = a->tv_sec - b->tv_sec;
129 tv->tv_usec = a->tv_usec - b->tv_usec;
130 if (((long) tv->tv_usec) < 0) {
131 tv->tv_sec--;
132 tv->tv_usec += 1000000;
133 }
134}
135
136void
Denys Vlasenko12014262011-05-30 14:00:14 +0200137tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138{
139 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
140 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
141 tv->tv_usec %= 1000000;
142}
143
144void
Denys Vlasenko12014262011-05-30 14:00:14 +0200145tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146{
147 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000148 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149 tv->tv_usec %= 1000000;
150}
151
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000152const char *
153xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154{
155 for (; xlat->str != NULL; xlat++)
156 if (xlat->val == val)
157 return xlat->str;
158 return NULL;
159}
160
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200161#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200162char *
163stpcpy(char *dst, const char *src)
164{
165 while ((*dst = *src++) != '\0')
166 dst++;
167 return dst;
168}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200169#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200170
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171/*
172 * Print entry in struct xlat table, if there.
173 */
174void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000175printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000177 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178
179 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200180 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181 else
182 tprintf("%#x /* %s */", val, dflt);
183}
184
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100185#if HAVE_LONG_LONG
186/*
187 * Print 64bit argument at position llarg and return the index of the next
188 * argument.
189 */
190int
191printllval(struct tcb *tcp, const char *format, int llarg)
192{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100193# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100194 if (current_personality == 0) {
195 tprintf(format, tcp->u_arg[llarg]);
196 llarg++;
197 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200198# ifdef POWERPC64
199 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200200 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200201# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100202 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
203 llarg += 2;
204 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200205# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100206 tprintf(format, tcp->u_arg[llarg]);
207 llarg++;
H.J. Lu35be5812012-04-16 13:00:01 +0200208# elif defined LINUX_MIPSN32 || defined X32
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100209 tprintf(format, tcp->ext_arg[llarg]);
210 llarg++;
211# else
212 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
213 llarg += 2;
214# endif
215 return llarg;
216}
217#endif
218
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000219/*
220 * Interpret `xlat' as an array of flags
221 * print the entries whose bits are on in `flags'
222 * return # of flags printed.
223 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200224void
Denys Vlasenko12014262011-05-30 14:00:14 +0200225addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000226{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200227 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228 if (xlat->val && (flags & xlat->val) == xlat->val) {
229 tprintf("|%s", xlat->str);
230 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 }
232 }
233 if (flags) {
234 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236}
237
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000238/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200239 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000240 * Print to static string the entries whose bits are on in `flags'
241 * Return static string.
242 */
243const char *
244sprintflags(const char *prefix, const struct xlat *xlat, int flags)
245{
246 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200247 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000248 int found = 0;
249
Denys Vlasenko52845572011-08-31 12:07:38 +0200250 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000251
252 for (; xlat->str; xlat++) {
253 if ((flags & xlat->val) == xlat->val) {
254 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200255 *outptr++ = '|';
256 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000257 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100258 flags &= ~xlat->val;
259 if (!flags)
260 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000261 }
262 }
263 if (flags) {
264 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200265 *outptr++ = '|';
266 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000267 }
268
269 return outstr;
270}
271
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000273printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000274{
275 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000276 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277
278 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200279 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000280 return 1;
281 }
282
283 sep = "";
284 for (n = 0; xlat->str; xlat++) {
285 if (xlat->val && (flags & xlat->val) == xlat->val) {
286 tprintf("%s%s", sep, xlat->str);
287 flags &= ~xlat->val;
288 sep = "|";
289 n++;
290 }
291 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000292
293 if (n) {
294 if (flags) {
295 tprintf("%s%#x", sep, flags);
296 n++;
297 }
298 } else {
299 if (flags) {
300 tprintf("%#x", flags);
301 if (dflt)
302 tprintf(" /* %s */", dflt);
303 } else {
304 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200305 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000306 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000308
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 return n;
310}
311
312void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000313printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314{
Roland McGratheb285352003-01-14 09:59:00 +0000315 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316
317 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200318 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319 return;
320 }
321 if (umove(tcp, addr, &num) < 0) {
322 tprintf("%#lx", addr);
323 return;
324 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200325 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200327 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328}
329
Roland McGrath6bc12202003-11-13 22:32:27 +0000330void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000331printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000332{
333 int num;
334
335 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200336 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000337 return;
338 }
339 if (umove(tcp, addr, &num) < 0) {
340 tprintf("%#lx", addr);
341 return;
342 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200343 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000344 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200345 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000346}
347
348void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300349printfd(struct tcb *tcp, int fd)
350{
Grant Edwards8a082772011-04-07 20:25:40 +0000351 const char *p;
352
353 if (show_fd_path && (p = getfdpath(tcp, fd)))
354 tprintf("%d<%s>", fd, p);
355 else
356 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300357}
358
359void
Denys Vlasenko12014262011-05-30 14:00:14 +0200360printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000361{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200362 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000363}
364
Dmitry V. Levina501f142008-11-10 23:19:13 +0000365/*
366 * Quote string `instr' of length `size'
367 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200368 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000369 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100370 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200371 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100372 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000373 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400374int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200375string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000377 const unsigned char *ustr = (const unsigned char *) instr;
378 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200379 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200381 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200382 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200383 size--;
384 eol = '\0';
385 }
386
387 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000388 if (xflag > 1)
389 usehex = 1;
390 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000391 /* Check for presence of symbol which require
392 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000393 for (i = 0; i < size; ++i) {
394 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000395 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200396 if (c == eol)
397 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000398 if (!isprint(c) && !isspace(c)) {
399 usehex = 1;
400 break;
401 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402 }
403 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000404
405 *s++ = '\"';
406
407 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000408 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000409 for (i = 0; i < size; ++i) {
410 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000411 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200412 if (c == eol)
413 goto asciz_ended;
414 *s++ = '\\';
415 *s++ = 'x';
416 *s++ = "0123456789abcdef"[c >> 4];
417 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000418 }
419 } else {
420 for (i = 0; i < size; ++i) {
421 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000422 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200423 if (c == eol)
424 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000425 switch (c) {
426 case '\"': case '\\':
427 *s++ = '\\';
428 *s++ = c;
429 break;
430 case '\f':
431 *s++ = '\\';
432 *s++ = 'f';
433 break;
434 case '\n':
435 *s++ = '\\';
436 *s++ = 'n';
437 break;
438 case '\r':
439 *s++ = '\\';
440 *s++ = 'r';
441 break;
442 case '\t':
443 *s++ = '\\';
444 *s++ = 't';
445 break;
446 case '\v':
447 *s++ = '\\';
448 *s++ = 'v';
449 break;
450 default:
451 if (isprint(c))
452 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200453 else {
454 /* Print \octal */
455 *s++ = '\\';
456 if (i + 1 < size
457 && ustr[i + 1] >= '0'
458 && ustr[i + 1] <= '9'
459 ) {
460 /* Print \ooo */
461 *s++ = '0' + (c >> 6);
462 *s++ = '0' + ((c >> 3) & 0x7);
463 } else {
464 /* Print \[[o]o]o */
465 if ((c >> 3) != 0) {
466 if ((c >> 6) != 0)
467 *s++ = '0' + (c >> 6);
468 *s++ = '0' + ((c >> 3) & 0x7);
469 }
470 }
471 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000472 }
473 break;
474 }
475 }
476 }
477
478 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000479 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000480
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200481 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200482 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200483 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
484 * but next char is NUL.
485 */
486 return 0;
487 }
488
489 return 1;
490
491 asciz_ended:
492 *s++ = '\"';
493 *s = '\0';
494 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
495 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000496}
497
Dmitry V. Levina501f142008-11-10 23:19:13 +0000498/*
499 * Print path string specified by address `addr' and length `n'.
500 * If path length exceeds `n', append `...' to the output.
501 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000502void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000503printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100505 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100506 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100507
Dmitry V. Levina501f142008-11-10 23:19:13 +0000508 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200509 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000510 return;
511 }
512
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100513 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000514 if (n > sizeof path - 1)
515 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000516
517 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100518 nul_seen = umovestr(tcp, addr, n + 1, path);
519 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520 tprintf("%#lx", addr);
521 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100522 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000523
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100524 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100525 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100526 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100527 string_quote(path, outstr, -1, n);
528 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100529 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100530 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 }
532}
533
534void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000535printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100537 /* Size must correspond to char path[] size in printpathn */
538 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000539}
540
Dmitry V. Levina501f142008-11-10 23:19:13 +0000541/*
542 * Print string specified by address `addr' and length `len'.
543 * If `len' < 0, treat the string as a NUL-terminated string.
544 * If string length exceeds `max_strlen', append `...' to the output.
545 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000546void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200547printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000548{
549 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000551 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100552 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553
554 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200555 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556 return;
557 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000558 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200559 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000560 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
561
562 if (outstr_size / 4 != max_strlen)
563 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000564 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200565 if (!str)
566 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000567 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200568 if (!outstr)
569 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000571
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200572 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000573 /*
574 * Treat as a NUL-terminated string: fetch one byte more
575 * because string_quote() quotes one byte less.
576 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000577 size = max_strlen + 1;
578 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000579 tprintf("%#lx", addr);
580 return;
581 }
582 }
583 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200584 size = max_strlen;
585 if (size > (unsigned long)len)
586 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000587 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 tprintf("%#lx", addr);
589 return;
590 }
591 }
592
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100593 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
594 * or we were requested to print more than -s NUM chars)...
595 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100596 ellipsis = (string_quote(str, outstr, len, size) &&
597 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000598
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100599 tprints(outstr);
600 if (ellipsis)
601 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602}
603
John Hughes1d08dcf2001-07-10 13:48:44 +0000604#if HAVE_SYS_UIO_H
605void
Denys Vlasenko12014262011-05-30 14:00:14 +0200606dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000607{
Denys Vlasenko84703742012-02-25 02:38:52 +0100608#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000609 union {
610 struct { u_int32_t base; u_int32_t len; } *iov32;
611 struct { u_int64_t base; u_int64_t len; } *iov64;
612 } iovu;
613#define iov iovu.iov64
614#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100615 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000616#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100617 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000618#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100619 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000620#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000621 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000622#define sizeof_iov sizeof(*iov)
623#define iov_iov_base(i) iov[i].iov_base
624#define iov_iov_len(i) iov[i].iov_len
625#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000626 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200627 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000628
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200629 size = sizeof_iov * len;
630 /* Assuming no sane program has millions of iovs */
631 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000632 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200633 fprintf(stderr, "Out of memory\n");
634 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000635 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000636 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000637 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000638 /* include the buffer number to make it easy to
639 * match up the trace with the source */
640 tprintf(" * %lu bytes in buffer %d\n",
641 (unsigned long)iov_iov_len(i), i);
642 dumpstr(tcp, (long) iov_iov_base(i),
643 iov_iov_len(i));
644 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000645 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200646 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000647#undef sizeof_iov
648#undef iov_iov_base
649#undef iov_iov_len
650#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000651}
652#endif
653
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654void
Denys Vlasenko12014262011-05-30 14:00:14 +0200655dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656{
657 static int strsize = -1;
658 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000659 char *s;
660 int i, j;
661
662 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200663 free(str);
664 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200665 if (!str) {
666 strsize = -1;
667 fprintf(stderr, "Out of memory\n");
668 return;
669 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670 strsize = len;
671 }
672
673 if (umoven(tcp, addr, len, (char *) str) < 0)
674 return;
675
676 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200677 char outstr[80];
678
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 s = outstr;
680 sprintf(s, " | %05x ", i);
681 s += 9;
682 for (j = 0; j < 16; j++) {
683 if (j == 8)
684 *s++ = ' ';
685 if (i + j < len) {
686 sprintf(s, " %02x", str[i + j]);
687 s += 3;
688 }
689 else {
690 *s++ = ' '; *s++ = ' '; *s++ = ' ';
691 }
692 }
693 *s++ = ' '; *s++ = ' ';
694 for (j = 0; j < 16; j++) {
695 if (j == 8)
696 *s++ = ' ';
697 if (i + j < len) {
698 if (isprint(str[i + j]))
699 *s++ = str[i + j];
700 else
701 *s++ = '.';
702 }
703 else
704 *s++ = ' ';
705 }
706 tprintf("%s |\n", outstr);
707 }
708}
709
Mike Frysinger612659e2012-02-14 14:38:28 +0100710#ifdef HAVE_PROCESS_VM_READV
711/* C library supports this, but the kernel might not. */
712static bool process_vm_readv_not_supported = 0;
713#else
714
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100715/* Need to do this since process_vm_readv() is not yet available in libc.
716 * When libc is be updated, only "static bool process_vm_readv_not_supported"
717 * line should remain.
718 */
719#if !defined(__NR_process_vm_readv)
720# if defined(I386)
721# define __NR_process_vm_readv 347
722# elif defined(X86_64)
723# define __NR_process_vm_readv 310
724# elif defined(POWERPC)
725# define __NR_process_vm_readv 351
726# endif
727#endif
728
729#if defined(__NR_process_vm_readv)
730static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400731/* Have to avoid duplicating with the C library headers. */
732static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100733 const struct iovec *lvec,
734 unsigned long liovcnt,
735 const struct iovec *rvec,
736 unsigned long riovcnt,
737 unsigned long flags)
738{
739 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
740}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400741#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100742#else
743static bool process_vm_readv_not_supported = 1;
744# define process_vm_readv(...) (errno = ENOSYS, -1)
745#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100746
747#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100748
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749#define PAGMASK (~(PAGSIZ - 1))
750/*
751 * move `len' bytes of data from process `pid'
752 * at address `addr' to our space at `laddr'
753 */
754int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000755umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700757 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100759 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 union {
761 long val;
762 char x[sizeof(long)];
763 } u;
764
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100765#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100766 if (current_wordsize < sizeof(addr))
767 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100768#endif
769
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100770 if (!process_vm_readv_not_supported) {
771 struct iovec local[1], remote[1];
772 int r;
773
774 local[0].iov_base = laddr;
775 remote[0].iov_base = (void*)addr;
776 local[0].iov_len = remote[0].iov_len = len;
777 r = process_vm_readv(pid,
778 local, 1,
779 remote, 1,
780 /*flags:*/ 0
781 );
782 if (r < 0) {
783 if (errno == ENOSYS)
784 process_vm_readv_not_supported = 1;
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000785 else if (errno != EINVAL && errno != ESRCH)
786 /* EINVAL or ESRCH could be seen if process is gone,
787 * all the rest is strange and should be reported. */
788 perror_msg("%s", "process_vm_readv");
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100789 goto vm_readv_didnt_work;
790 }
791 return r;
792 }
793 vm_readv_didnt_work:
794
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100795 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 if (addr & (sizeof(long) - 1)) {
797 /* addr not a multiple of sizeof(long) */
798 n = addr - (addr & -sizeof(long)); /* residue */
799 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700800 errno = 0;
801 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
802 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700803 /* But if not started, we had a bogus address. */
804 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100805 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700806 return -1;
807 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000808 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100809 m = MIN(sizeof(long) - n, len);
810 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 addr += sizeof(long), laddr += m, len -= m;
812 }
813 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700814 errno = 0;
815 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
816 if (errno) {
817 if (started && (errno==EPERM || errno==EIO)) {
818 /* Ran into 'end of memory' - stupid "printpath" */
819 return 0;
820 }
821 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100822 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700823 return -1;
824 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000825 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100826 m = MIN(sizeof(long), len);
827 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 addr += sizeof(long), laddr += m, len -= m;
829 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831 return 0;
832}
833
834/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100835 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100837 *
838 * Returns < 0 on error, > 0 if NUL was seen,
839 * (TODO if useful: return count of bytes including NUL),
840 * else 0 if len bytes were read but no NUL byte seen.
841 *
842 * Note: there is no guarantee we won't overwrite some bytes
843 * in laddr[] _after_ terminating NUL (but, of course,
844 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 */
846int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000847umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000848{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100849 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700850 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 int i, n, m;
852 union {
853 long val;
854 char x[sizeof(long)];
855 } u;
856
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000857#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100858 if (current_wordsize < sizeof(addr))
859 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000860#endif
861
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100862 if (!process_vm_readv_not_supported) {
863 struct iovec local[1], remote[1];
864
865 local[0].iov_base = laddr;
866 remote[0].iov_base = (void*)addr;
867
868 while (len > 0) {
869 int end_in_page;
870 int r;
871 int chunk_len;
872
873 /* Don't read kilobytes: most strings are short */
874 chunk_len = len;
875 if (chunk_len > 256)
876 chunk_len = 256;
877 /* Don't cross pages. I guess otherwise we can get EFAULT
878 * and fail to notice that terminating NUL lies
879 * in the existing (first) page.
880 * (I hope there aren't arches with pages < 4K)
881 */
882 end_in_page = ((addr + chunk_len) & 4095);
883 r = chunk_len - end_in_page;
884 if (r > 0) /* if chunk_len > end_in_page */
885 chunk_len = r; /* chunk_len -= end_in_page */
886
887 local[0].iov_len = remote[0].iov_len = chunk_len;
888 r = process_vm_readv(pid,
889 local, 1,
890 remote, 1,
891 /*flags:*/ 0
892 );
893 if (r < 0) {
894 if (errno == ENOSYS)
895 process_vm_readv_not_supported = 1;
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000896 else if (errno != EINVAL && errno != ESRCH)
897 /* EINVAL or ESRCH could be seen
898 * if process is gone, all the rest
899 * is strange and should be reported. */
900 perror_msg("%s", "process_vm_readv");
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100901 goto vm_readv_didnt_work;
902 }
903 if (memchr(local[0].iov_base, '\0', r))
904 return 1;
905 local[0].iov_base += r;
906 remote[0].iov_base += r;
907 len -= r;
908 }
909 return 0;
910 }
911 vm_readv_didnt_work:
912
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100913 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914 if (addr & (sizeof(long) - 1)) {
915 /* addr not a multiple of sizeof(long) */
916 n = addr - (addr & -sizeof(long)); /* residue */
917 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700918 errno = 0;
919 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
920 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700921 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100922 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700923 return -1;
924 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000925 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100926 m = MIN(sizeof(long) - n, len);
927 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 while (n & (sizeof(long) - 1))
929 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100930 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 addr += sizeof(long), laddr += m, len -= m;
932 }
933 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700934 errno = 0;
935 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
936 if (errno) {
937 if (started && (errno==EPERM || errno==EIO)) {
938 /* Ran into 'end of memory' - stupid "printpath" */
939 return 0;
940 }
941 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100942 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700943 return -1;
944 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000945 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100946 m = MIN(sizeof(long), len);
947 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 for (i = 0; i < sizeof(long); i++)
949 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100950 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 addr += sizeof(long), laddr += m, len -= m;
952 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000953 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954}
955
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956int
Denys Vlasenko12014262011-05-30 14:00:14 +0200957upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958{
959 long val;
960
Roland McGratheb9e2e82009-06-02 16:49:22 -0700961 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100962 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700963 if (val == -1 && errno) {
964 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100965 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700966 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700968 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 *res = val;
970 return 0;
971}
972
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000973/*
974 * These #if's are huge, please indent them correctly.
975 * It's easy to get confused otherwise.
976 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100978#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +0000979
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100980#ifndef CLONE_PTRACE
981# define CLONE_PTRACE 0x00002000
982#endif
983#ifndef CLONE_VFORK
984# define CLONE_VFORK 0x00004000
985#endif
986#ifndef CLONE_VM
987# define CLONE_VM 0x00000100
988#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +0000989
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100990#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +0000991
992typedef unsigned long *arg_setup_state;
993
994static int
995arg_setup(struct tcb *tcp, arg_setup_state *state)
996{
Jan Kratochvil1f942712008-08-06 21:38:52 +0000997 unsigned long cfm, sof, sol;
998 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +0000999
Jan Kratochvil1f942712008-08-06 21:38:52 +00001000 if (ia32) {
1001 /* Satisfy a false GCC warning. */
1002 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001003 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001004 }
Roland McGrath08267b82004-02-20 22:56:43 +00001005
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001006 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001007 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001008 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001009 return -1;
1010
1011 sof = (cfm >> 0) & 0x7f;
1012 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001013 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001014
Jan Kratochvil1f942712008-08-06 21:38:52 +00001015 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001016 return 0;
1017}
1018
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001019# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001020
Roland McGrathd81f1d92003-01-09 06:53:34 +00001021static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001022get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001023{
Roland McGrath08267b82004-02-20 22:56:43 +00001024 int ret;
1025
1026 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001027 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001028 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001029 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001030 (unsigned long) ia64_rse_skip_regs(*state, 0),
1031 sizeof(long), (void *) valp);
1032 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001033}
1034
1035static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001036get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001037{
Roland McGrath08267b82004-02-20 22:56:43 +00001038 int ret;
1039
1040 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001041 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001042 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001043 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001044 (unsigned long) ia64_rse_skip_regs(*state, 1),
1045 sizeof(long), (void *) valp);
1046 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001047}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001048
1049static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001050set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001051{
Roland McGrath08267b82004-02-20 22:56:43 +00001052 int req = PTRACE_POKEDATA;
1053 void *ap;
1054
1055 if (ia32) {
1056 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1057 req = PTRACE_POKEUSER;
1058 } else
1059 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001060 errno = 0;
1061 ptrace(req, tcp->pid, ap, val);
1062 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001063}
1064
1065static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001066set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001067{
Roland McGrath08267b82004-02-20 22:56:43 +00001068 int req = PTRACE_POKEDATA;
1069 void *ap;
1070
1071 if (ia32) {
1072 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1073 req = PTRACE_POKEUSER;
1074 } else
1075 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001076 errno = 0;
1077 ptrace(req, tcp->pid, ap, val);
1078 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001079}
1080
Roland McGrathb659f872008-07-18 01:19:36 +00001081/* ia64 does not return the input arguments from functions (and syscalls)
1082 according to ia64 RSE (Register Stack Engine) behavior. */
1083
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001084# define restore_arg0(tcp, state, val) ((void) (state), 0)
1085# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001086
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001087#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001088
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001089# if defined(SPARC64)
1090# undef PTRACE_GETREGS
1091# define PTRACE_GETREGS PTRACE_GETREGS64
1092# undef PTRACE_SETREGS
1093# define PTRACE_SETREGS PTRACE_SETREGS64
1094# endif
1095
Mike Frysinger8566c502009-10-12 11:05:14 -04001096typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001097
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001098# define arg_setup(tcp, state) \
1099 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1100# define arg_finish_change(tcp, state) \
1101 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001102
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001103# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1104# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1105# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1106# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1107# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001108
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001109#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001110
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001111# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001112/* Note: this is only true for the `clone' system call, which handles
1113 arguments specially. We could as well say that its first two arguments
1114 are swapped relative to other architectures, but that would just be
1115 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001116# define arg0_offset PT_GPR3
1117# define arg1_offset PT_ORIGGPR2
1118# define restore_arg0(tcp, state, val) ((void) (state), 0)
1119# define restore_arg1(tcp, state, val) ((void) (state), 0)
1120# define arg0_index 1
1121# define arg1_index 0
1122# elif defined(ALPHA) || defined(MIPS)
1123# define arg0_offset REG_A0
1124# define arg1_offset (REG_A0+1)
1125# elif defined(AVR32)
1126# define arg0_offset (REG_R12)
1127# define arg1_offset (REG_R11)
1128# 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
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001153# elif defined TILE
1154# define arg0_offset PTREGS_OFFSET_REG(0)
1155# define arg1_offset PTREGS_OFFSET_REG(1)
1156# define restore_arg0(tcp, state, val) 0
1157# define restore_arg1(tcp, state, val) 0
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001158# else
1159# define arg0_offset 0
1160# define arg1_offset 4
1161# if defined ARM
1162# define restore_arg0(tcp, state, val) 0
1163# endif
1164# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001165
1166typedef int arg_setup_state;
1167
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001168# define arg_setup(tcp, state) (0)
1169# define arg_finish_change(tcp, state) 0
1170# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1171# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172
1173static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001174set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001175{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001176 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001177}
1178
1179static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001180set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001181{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001182 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001183}
1184
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001185#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001186
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001187#ifndef restore_arg0
1188# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1189#endif
1190#ifndef restore_arg1
1191# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1192#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001193
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001194#ifndef arg0_index
1195# define arg0_index 0
1196# define arg1_index 1
1197#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001198
James Hogan05eb9052012-11-29 17:37:37 +00001199static int
1200change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1201{
1202#if defined(I386)
1203 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1204 return -1;
1205 return 0;
1206#elif defined(X86_64) || defined(X32)
1207 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1208 return -1;
1209 return 0;
1210#elif defined(POWERPC)
1211 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1212 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1213 return -1;
1214 return 0;
1215#elif defined(S390) || defined(S390X)
1216 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1217 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1218 return -1;
1219 return 0;
1220#elif defined(M68K)
1221 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1222 return -1;
1223 return 0;
1224#elif defined(SPARC) || defined(SPARC64)
1225 state->u_regs[U_REG_G1] = new;
1226 return 0;
1227#elif defined(MIPS)
1228 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1229 return -1;
1230 return 0;
1231#elif defined(ALPHA)
1232 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1233 return -1;
1234 return 0;
1235#elif defined(AVR32)
1236 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1237 return -1;
1238 return 0;
1239#elif defined(BFIN)
1240 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1241 return -1;
1242 return 0;
1243#elif defined(IA64)
1244 if (ia32) {
1245 switch (new) {
1246 case 2:
1247 break; /* x86 SYS_fork */
1248 case SYS_clone:
1249 new = 120;
1250 break;
1251 default:
1252 fprintf(stderr, "%s: unexpected syscall %d\n",
1253 __FUNCTION__, new);
1254 return -1;
1255 }
1256 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1257 return -1;
1258 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1259 return -1;
1260 return 0;
1261#elif defined(HPPA)
1262 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1263 return -1;
1264 return 0;
1265#elif defined(SH)
1266 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1267 return -1;
1268 return 0;
1269#elif defined(SH64)
1270 /* Top half of reg encodes the no. of args n as 0x1n.
1271 Assume 0 args as kernel never actually checks... */
1272 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1273 0x100000 | new) < 0)
1274 return -1;
1275 return 0;
1276#elif defined(CRISV10) || defined(CRISV32)
1277 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1278 return -1;
1279 return 0;
1280#elif defined(ARM)
1281 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1282# ifndef PTRACE_SET_SYSCALL
1283# define PTRACE_SET_SYSCALL 23
1284# endif
1285 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1286 return -1;
1287 return 0;
1288#elif defined(TILE)
1289 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1290 (char*)PTREGS_OFFSET_REG(0),
1291 new) != 0)
1292 return -1;
1293 return 0;
1294#elif defined(MICROBLAZE)
1295 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1296 return -1;
1297 return 0;
1298#else
1299#warning Do not know how to handle change_syscall for this architecture
1300#endif /* architecture */
1301 return -1;
1302}
1303
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001305setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001306{
Roland McGrath3291ef22008-05-20 00:34:34 +00001307 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001308 arg_setup_state state;
1309
1310 if (tcp->flags & TCB_BPTSET) {
1311 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1312 return -1;
1313 }
1314
Roland McGrath3291ef22008-05-20 00:34:34 +00001315 /*
1316 * It's a silly kludge to initialize this with a search at runtime.
1317 * But it's better than maintaining another magic thing in the
1318 * godforsaken tables.
1319 */
1320 if (clone_scno[current_personality] == 0) {
1321 int i;
1322 for (i = 0; i < nsyscalls; ++i)
1323 if (sysent[i].sys_func == sys_clone) {
1324 clone_scno[current_personality] = i;
1325 break;
1326 }
1327 }
1328
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001329 if (sysent[tcp->scno].sys_func == sys_fork ||
1330 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001331 if (arg_setup(tcp, &state) < 0
1332 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1333 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001334 || change_syscall(tcp, &state,
1335 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001336 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1337 || set_arg1(tcp, &state, 0) < 0
1338 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001340 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1341 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342 tcp->flags |= TCB_BPTSET;
1343 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001344 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001345
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001346 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001347 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001348 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001349 vfork semantics into plain fork - each application must not
1350 depend on the vfork specifics according to POSIX. We would
1351 hang waiting for the parent resume otherwise. We need to
1352 clear also CLONE_VM but only in the CLONE_VFORK case as
1353 otherwise we would break pthread_create. */
1354
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001355 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1356 if (new_arg0 & CLONE_VFORK)
1357 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1358 if (arg_setup(tcp, &state) < 0
1359 || set_arg0(tcp, &state, new_arg0) < 0
1360 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001361 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001362 tcp->inst[0] = tcp->u_arg[arg0_index];
1363 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001364 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366 }
1367
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001368 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1369 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001370 return -1;
1371}
1372
1373int
Denys Vlasenko12014262011-05-30 14:00:14 +02001374clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001375{
1376 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001377 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001378 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001379 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1380 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1381 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001382 if (errno != ESRCH)
1383 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001384 tcp->flags &= ~TCB_BPTSET;
1385 return 0;
1386}