blob: ea3488d4afa3dbdd1cb0ab35e3340378349727c0 [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 __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
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010067#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000068# undef PTRACE_GETREGS
69# define PTRACE_GETREGS PTRACE_GETREGS64
70# undef PTRACE_SETREGS
71# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000072#endif
73
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074/* macros */
75#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010076# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
78#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010079# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#endif
81
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000083string_to_uint(const char *str)
84{
85 char *error;
86 long value;
87
88 if (!*str)
89 return -1;
90 errno = 0;
91 value = strtol(str, &error, 10);
92 if (errno || *error || value < 0 || (long)(int)value != value)
93 return -1;
94 return (int)value;
95}
96
97int
Denys Vlasenko12014262011-05-30 14:00:14 +020098tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099{
100 return a->tv_sec || a->tv_usec;
101}
102
103int
Denys Vlasenko12014262011-05-30 14:00:14 +0200104tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105{
106 if (a->tv_sec < b->tv_sec
107 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
108 return -1;
109 if (a->tv_sec > b->tv_sec
110 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
111 return 1;
112 return 0;
113}
114
115double
Denys Vlasenko12014262011-05-30 14:00:14 +0200116tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117{
118 return tv->tv_sec + tv->tv_usec/1000000.0;
119}
120
121void
Denys Vlasenko12014262011-05-30 14:00:14 +0200122tv_add(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;
Roland McGrath58372f52007-07-24 01:38:22 +0000126 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127 tv->tv_sec++;
128 tv->tv_usec -= 1000000;
129 }
130}
131
132void
Denys Vlasenko12014262011-05-30 14:00:14 +0200133tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134{
135 tv->tv_sec = a->tv_sec - b->tv_sec;
136 tv->tv_usec = a->tv_usec - b->tv_usec;
137 if (((long) tv->tv_usec) < 0) {
138 tv->tv_sec--;
139 tv->tv_usec += 1000000;
140 }
141}
142
143void
Denys Vlasenko12014262011-05-30 14:00:14 +0200144tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145{
146 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
147 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
148 tv->tv_usec %= 1000000;
149}
150
151void
Denys Vlasenko12014262011-05-30 14:00:14 +0200152tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153{
154 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000155 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156 tv->tv_usec %= 1000000;
157}
158
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000159const char *
160xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161{
162 for (; xlat->str != NULL; xlat++)
163 if (xlat->val == val)
164 return xlat->str;
165 return NULL;
166}
167
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200168#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200169char *
170stpcpy(char *dst, const char *src)
171{
172 while ((*dst = *src++) != '\0')
173 dst++;
174 return dst;
175}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200176#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200177
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178/*
179 * Print entry in struct xlat table, if there.
180 */
181void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000182printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000184 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185
186 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200187 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188 else
189 tprintf("%#x /* %s */", val, dflt);
190}
191
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100192#if HAVE_LONG_LONG
193/*
194 * Print 64bit argument at position llarg and return the index of the next
195 * argument.
196 */
197int
198printllval(struct tcb *tcp, const char *format, int llarg)
199{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100200# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100201 if (current_personality == 0) {
202 tprintf(format, tcp->u_arg[llarg]);
203 llarg++;
204 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200205# ifdef POWERPC64
206 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200207 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200208# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100209 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
210 llarg += 2;
211 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200212# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100213 tprintf(format, tcp->u_arg[llarg]);
214 llarg++;
215# elif defined LINUX_MIPSN32
216 tprintf(format, tcp->ext_arg[llarg]);
217 llarg++;
218# else
219 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
220 llarg += 2;
221# endif
222 return llarg;
223}
224#endif
225
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000226/*
227 * Interpret `xlat' as an array of flags
228 * print the entries whose bits are on in `flags'
229 * return # of flags printed.
230 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200231void
Denys Vlasenko12014262011-05-30 14:00:14 +0200232addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200234 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 if (xlat->val && (flags & xlat->val) == xlat->val) {
236 tprintf("|%s", xlat->str);
237 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238 }
239 }
240 if (flags) {
241 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000243}
244
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000245/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200246 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000247 * Print to static string the entries whose bits are on in `flags'
248 * Return static string.
249 */
250const char *
251sprintflags(const char *prefix, const struct xlat *xlat, int flags)
252{
253 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200254 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000255 int found = 0;
256
Denys Vlasenko52845572011-08-31 12:07:38 +0200257 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000258
259 for (; xlat->str; xlat++) {
260 if ((flags & xlat->val) == xlat->val) {
261 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200262 *outptr++ = '|';
263 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000264 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100265 flags &= ~xlat->val;
266 if (!flags)
267 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000268 }
269 }
270 if (flags) {
271 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200272 *outptr++ = '|';
273 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000274 }
275
276 return outstr;
277}
278
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000279int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000280printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281{
282 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000283 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284
285 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200286 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287 return 1;
288 }
289
290 sep = "";
291 for (n = 0; xlat->str; xlat++) {
292 if (xlat->val && (flags & xlat->val) == xlat->val) {
293 tprintf("%s%s", sep, xlat->str);
294 flags &= ~xlat->val;
295 sep = "|";
296 n++;
297 }
298 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000299
300 if (n) {
301 if (flags) {
302 tprintf("%s%#x", sep, flags);
303 n++;
304 }
305 } else {
306 if (flags) {
307 tprintf("%#x", flags);
308 if (dflt)
309 tprintf(" /* %s */", dflt);
310 } else {
311 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200312 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000313 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000315
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316 return n;
317}
318
319void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000320printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321{
Roland McGratheb285352003-01-14 09:59:00 +0000322 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000323
324 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200325 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 return;
327 }
328 if (umove(tcp, addr, &num) < 0) {
329 tprintf("%#lx", addr);
330 return;
331 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200332 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200334 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000335}
336
Roland McGrath6bc12202003-11-13 22:32:27 +0000337void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000338printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000339{
340 int num;
341
342 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200343 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000344 return;
345 }
346 if (umove(tcp, addr, &num) < 0) {
347 tprintf("%#lx", addr);
348 return;
349 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200350 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000351 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200352 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000353}
354
355void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300356printfd(struct tcb *tcp, int fd)
357{
Grant Edwards8a082772011-04-07 20:25:40 +0000358 const char *p;
359
360 if (show_fd_path && (p = getfdpath(tcp, fd)))
361 tprintf("%d<%s>", fd, p);
362 else
363 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300364}
365
366void
Denys Vlasenko12014262011-05-30 14:00:14 +0200367printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000368{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200369 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000370}
371
Dmitry V. Levina501f142008-11-10 23:19:13 +0000372/*
373 * Quote string `instr' of length `size'
374 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
375 * If `len' < 0, treat `instr' as a NUL-terminated string
376 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100377 *
378 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
379 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000380 */
Roland McGrath6d970322007-11-01 23:53:59 +0000381static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000382string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000384 const unsigned char *ustr = (const unsigned char *) instr;
385 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200386 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200388 eol = 0x100; /* this can never match a char */
389 if (len < 0) {
390 size--;
391 eol = '\0';
392 }
393
394 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000395 if (xflag > 1)
396 usehex = 1;
397 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000398 /* Check for presence of symbol which require
399 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000400 for (i = 0; i < size; ++i) {
401 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000402 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200403 if (c == eol)
404 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000405 if (!isprint(c) && !isspace(c)) {
406 usehex = 1;
407 break;
408 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 }
410 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000411
412 *s++ = '\"';
413
414 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000415 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000416 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;
421 *s++ = '\\';
422 *s++ = 'x';
423 *s++ = "0123456789abcdef"[c >> 4];
424 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000425 }
426 } else {
427 for (i = 0; i < size; ++i) {
428 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000429 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200430 if (c == eol)
431 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000432 switch (c) {
433 case '\"': case '\\':
434 *s++ = '\\';
435 *s++ = c;
436 break;
437 case '\f':
438 *s++ = '\\';
439 *s++ = 'f';
440 break;
441 case '\n':
442 *s++ = '\\';
443 *s++ = 'n';
444 break;
445 case '\r':
446 *s++ = '\\';
447 *s++ = 'r';
448 break;
449 case '\t':
450 *s++ = '\\';
451 *s++ = 't';
452 break;
453 case '\v':
454 *s++ = '\\';
455 *s++ = 'v';
456 break;
457 default:
458 if (isprint(c))
459 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200460 else {
461 /* Print \octal */
462 *s++ = '\\';
463 if (i + 1 < size
464 && ustr[i + 1] >= '0'
465 && ustr[i + 1] <= '9'
466 ) {
467 /* Print \ooo */
468 *s++ = '0' + (c >> 6);
469 *s++ = '0' + ((c >> 3) & 0x7);
470 } else {
471 /* Print \[[o]o]o */
472 if ((c >> 3) != 0) {
473 if ((c >> 6) != 0)
474 *s++ = '0' + (c >> 6);
475 *s++ = '0' + ((c >> 3) & 0x7);
476 }
477 }
478 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000479 }
480 break;
481 }
482 }
483 }
484
485 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000486 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000487
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200488 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
489 if (len < 0 && ustr[i] == '\0') {
490 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
491 * but next char is NUL.
492 */
493 return 0;
494 }
495
496 return 1;
497
498 asciz_ended:
499 *s++ = '\"';
500 *s = '\0';
501 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
502 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000503}
504
Dmitry V. Levina501f142008-11-10 23:19:13 +0000505/*
506 * Print path string specified by address `addr' and length `n'.
507 * If path length exceeds `n', append `...' to the output.
508 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000510printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100512 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100513 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100514
Dmitry V. Levina501f142008-11-10 23:19:13 +0000515 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200516 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000517 return;
518 }
519
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100520 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000521 if (n > sizeof path - 1)
522 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000523
524 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100525 nul_seen = umovestr(tcp, addr, n + 1, path);
526 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527 tprintf("%#lx", addr);
528 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100529 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000530
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100531 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100532 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100533 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100534 string_quote(path, outstr, -1, n);
535 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100536 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100537 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 }
539}
540
541void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000542printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100544 /* Size must correspond to char path[] size in printpathn */
545 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000546}
547
Dmitry V. Levina501f142008-11-10 23:19:13 +0000548/*
549 * Print string specified by address `addr' and length `len'.
550 * If `len' < 0, treat the string as a NUL-terminated string.
551 * If string length exceeds `max_strlen', append `...' to the output.
552 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553void
554printstr(struct tcb *tcp, long addr, int len)
555{
556 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000558 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100559 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560
561 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200562 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 return;
564 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000565 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200566 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000567 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200568 if (!str)
569 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100570 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200571 if (!outstr)
572 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000573 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000576 /*
577 * Treat as a NUL-terminated string: fetch one byte more
578 * because string_quote() quotes one byte less.
579 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000580 size = max_strlen + 1;
581 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000582 tprintf("%#lx", addr);
583 return;
584 }
585 }
586 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000587 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000588 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000589 tprintf("%#lx", addr);
590 return;
591 }
592 }
593
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100594 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
595 * or we were requested to print more than -s NUM chars)...
596 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100597 ellipsis = (string_quote(str, outstr, len, size) &&
598 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000599
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100600 tprints(outstr);
601 if (ellipsis)
602 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000603}
604
John Hughes1d08dcf2001-07-10 13:48:44 +0000605#if HAVE_SYS_UIO_H
606void
Denys Vlasenko12014262011-05-30 14:00:14 +0200607dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000608{
Denys Vlasenko84703742012-02-25 02:38:52 +0100609#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000610 union {
611 struct { u_int32_t base; u_int32_t len; } *iov32;
612 struct { u_int64_t base; u_int64_t len; } *iov64;
613 } iovu;
614#define iov iovu.iov64
615#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100616 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000617#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100618 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000619#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100620 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000621#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000622 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000623#define sizeof_iov sizeof(*iov)
624#define iov_iov_base(i) iov[i].iov_base
625#define iov_iov_len(i) iov[i].iov_len
626#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000627 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200628 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000629
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200630 size = sizeof_iov * len;
631 /* Assuming no sane program has millions of iovs */
632 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000633 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200634 fprintf(stderr, "Out of memory\n");
635 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000636 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000637 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000638 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000639 /* include the buffer number to make it easy to
640 * match up the trace with the source */
641 tprintf(" * %lu bytes in buffer %d\n",
642 (unsigned long)iov_iov_len(i), i);
643 dumpstr(tcp, (long) iov_iov_base(i),
644 iov_iov_len(i));
645 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000646 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200647 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000648#undef sizeof_iov
649#undef iov_iov_base
650#undef iov_iov_len
651#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000652}
653#endif
654
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655void
Denys Vlasenko12014262011-05-30 14:00:14 +0200656dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657{
658 static int strsize = -1;
659 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000660 char *s;
661 int i, j;
662
663 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200664 free(str);
665 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200666 if (!str) {
667 strsize = -1;
668 fprintf(stderr, "Out of memory\n");
669 return;
670 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671 strsize = len;
672 }
673
674 if (umoven(tcp, addr, len, (char *) str) < 0)
675 return;
676
677 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200678 char outstr[80];
679
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680 s = outstr;
681 sprintf(s, " | %05x ", i);
682 s += 9;
683 for (j = 0; j < 16; j++) {
684 if (j == 8)
685 *s++ = ' ';
686 if (i + j < len) {
687 sprintf(s, " %02x", str[i + j]);
688 s += 3;
689 }
690 else {
691 *s++ = ' '; *s++ = ' '; *s++ = ' ';
692 }
693 }
694 *s++ = ' '; *s++ = ' ';
695 for (j = 0; j < 16; j++) {
696 if (j == 8)
697 *s++ = ' ';
698 if (i + j < len) {
699 if (isprint(str[i + j]))
700 *s++ = str[i + j];
701 else
702 *s++ = '.';
703 }
704 else
705 *s++ = ' ';
706 }
707 tprintf("%s |\n", outstr);
708 }
709}
710
Mike Frysinger612659e2012-02-14 14:38:28 +0100711#ifdef HAVE_PROCESS_VM_READV
712/* C library supports this, but the kernel might not. */
713static bool process_vm_readv_not_supported = 0;
714#else
715
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100716/* Need to do this since process_vm_readv() is not yet available in libc.
717 * When libc is be updated, only "static bool process_vm_readv_not_supported"
718 * line should remain.
719 */
720#if !defined(__NR_process_vm_readv)
721# if defined(I386)
722# define __NR_process_vm_readv 347
723# elif defined(X86_64)
724# define __NR_process_vm_readv 310
725# elif defined(POWERPC)
726# define __NR_process_vm_readv 351
727# endif
728#endif
729
730#if defined(__NR_process_vm_readv)
731static bool process_vm_readv_not_supported = 0;
732static ssize_t process_vm_readv(pid_t pid,
733 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}
741#else
742static bool process_vm_readv_not_supported = 1;
743# define process_vm_readv(...) (errno = ENOSYS, -1)
744#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100745
746#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100747
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000748#define PAGMASK (~(PAGSIZ - 1))
749/*
750 * move `len' bytes of data from process `pid'
751 * at address `addr' to our space at `laddr'
752 */
753int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000754umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000755{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700756 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100758 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759 union {
760 long val;
761 char x[sizeof(long)];
762 } u;
763
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100764#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100765 if (current_wordsize < sizeof(addr))
766 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100767#endif
768
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100769 if (!process_vm_readv_not_supported) {
770 struct iovec local[1], remote[1];
771 int r;
772
773 local[0].iov_base = laddr;
774 remote[0].iov_base = (void*)addr;
775 local[0].iov_len = remote[0].iov_len = len;
776 r = process_vm_readv(pid,
777 local, 1,
778 remote, 1,
779 /*flags:*/ 0
780 );
781 if (r < 0) {
782 if (errno == ENOSYS)
783 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100784 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
785 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100786 perror("process_vm_readv");
787 goto vm_readv_didnt_work;
788 }
789 return r;
790 }
791 vm_readv_didnt_work:
792
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100793 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 if (addr & (sizeof(long) - 1)) {
795 /* addr not a multiple of sizeof(long) */
796 n = addr - (addr & -sizeof(long)); /* residue */
797 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700798 errno = 0;
799 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
800 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700801 /* But if not started, we had a bogus address. */
802 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100803 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700804 return -1;
805 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000806 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100807 m = MIN(sizeof(long) - n, len);
808 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000809 addr += sizeof(long), laddr += m, len -= m;
810 }
811 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700812 errno = 0;
813 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
814 if (errno) {
815 if (started && (errno==EPERM || errno==EIO)) {
816 /* Ran into 'end of memory' - stupid "printpath" */
817 return 0;
818 }
819 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100820 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700821 return -1;
822 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000823 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100824 m = MIN(sizeof(long), len);
825 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 addr += sizeof(long), laddr += m, len -= m;
827 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829 return 0;
830}
831
832/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100833 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100835 *
836 * Returns < 0 on error, > 0 if NUL was seen,
837 * (TODO if useful: return count of bytes including NUL),
838 * else 0 if len bytes were read but no NUL byte seen.
839 *
840 * Note: there is no guarantee we won't overwrite some bytes
841 * in laddr[] _after_ terminating NUL (but, of course,
842 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000843 */
844int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000845umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100847 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700848 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000849 int i, n, m;
850 union {
851 long val;
852 char x[sizeof(long)];
853 } u;
854
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000855#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100856 if (current_wordsize < sizeof(addr))
857 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000858#endif
859
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100860 if (!process_vm_readv_not_supported) {
861 struct iovec local[1], remote[1];
862
863 local[0].iov_base = laddr;
864 remote[0].iov_base = (void*)addr;
865
866 while (len > 0) {
867 int end_in_page;
868 int r;
869 int chunk_len;
870
871 /* Don't read kilobytes: most strings are short */
872 chunk_len = len;
873 if (chunk_len > 256)
874 chunk_len = 256;
875 /* Don't cross pages. I guess otherwise we can get EFAULT
876 * and fail to notice that terminating NUL lies
877 * in the existing (first) page.
878 * (I hope there aren't arches with pages < 4K)
879 */
880 end_in_page = ((addr + chunk_len) & 4095);
881 r = chunk_len - end_in_page;
882 if (r > 0) /* if chunk_len > end_in_page */
883 chunk_len = r; /* chunk_len -= end_in_page */
884
885 local[0].iov_len = remote[0].iov_len = chunk_len;
886 r = process_vm_readv(pid,
887 local, 1,
888 remote, 1,
889 /*flags:*/ 0
890 );
891 if (r < 0) {
892 if (errno == ENOSYS)
893 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100894 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
895 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100896 perror("process_vm_readv");
897 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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000970printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971{
Roland McGrath7a918832005-02-02 20:55:23 +0000972#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
973 sizeof(long) == 8 ? "[????????????????] " : \
974 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100976#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 long eip;
978
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000979 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +0000980 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 return;
982 }
983 tprintf("[%08lx] ", eip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100984#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000985 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200986 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000987 PRINTBADPC;
988 return;
989 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100990# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000991 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100992# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000993 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100994# endif
Roland McGratheac26fc2005-02-02 02:48:53 +0000995
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100996#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +0000997 long rip;
998
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000999 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001000 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001001 return;
1002 }
1003 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001004#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001005 long ip;
1006
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001007 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001008 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001009 return;
1010 }
1011 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001012#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 long pc;
1014
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001015 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001016 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 return;
1018 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001019# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001020 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001021# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001023# endif
1024#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 long pc;
1026
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001027 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001028 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 return;
1030 }
1031 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001032#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 long pc;
1034
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001035 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001036 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 return;
1038 }
1039 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001040#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001041 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001042 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001043 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044 return;
1045 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001046# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001047 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001048# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001049 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001050# endif
1051#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001052 long pc;
1053
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001054 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001055 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001056 return;
1057 }
1058 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001059#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001060 long pc;
1061
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001062 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001063 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001064 return;
1065 }
1066 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001067#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001068 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001069
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001071 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001072 return;
1073 }
1074 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001075#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001076 long pc;
1077
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001078 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001079 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001080 return;
1081 }
1082 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001083#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001084 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001085
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001086 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001087 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001088 return;
1089 }
1090 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001091#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001092 long pc;
1093
1094 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001095 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001096 return;
1097 }
1098 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001099#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001100 long pc;
1101
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001102 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001103 PRINTBADPC;
1104 return;
1105 }
1106 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001107#elif defined(CRISV10)
1108 long pc;
1109
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001110 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001111 PRINTBADPC;
1112 return;
1113 }
1114 tprintf("[%08lx] ", pc);
1115#elif defined(CRISV32)
1116 long pc;
1117
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001118 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001119 PRINTBADPC;
1120 return;
1121 }
1122 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001123#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124}
1125
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001126/*
1127 * These #if's are huge, please indent them correctly.
1128 * It's easy to get confused otherwise.
1129 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001131#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001132
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001133#ifndef CLONE_PTRACE
1134# define CLONE_PTRACE 0x00002000
1135#endif
1136#ifndef CLONE_VFORK
1137# define CLONE_VFORK 0x00004000
1138#endif
1139#ifndef CLONE_VM
1140# define CLONE_VM 0x00000100
1141#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001142
Denys Vlasenko081533c2012-03-17 02:17:51 +01001143static int
1144change_syscall(struct tcb *tcp, int new)
1145{
1146#if defined(I386)
1147 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1148 return -1;
1149 return 0;
1150#elif defined(X86_64)
1151 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1152 return -1;
1153 return 0;
1154#elif defined(POWERPC)
1155 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1156 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1157 return -1;
1158 return 0;
1159#elif defined(S390) || defined(S390X)
1160 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1161 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1162 return -1;
1163 return 0;
1164#elif defined(M68K)
1165 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1166 return -1;
1167 return 0;
1168#elif defined(SPARC) || defined(SPARC64)
1169 struct pt_regs regs;
1170 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1171 return -1;
1172 regs.u_regs[U_REG_G1] = new;
1173 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1174 return -1;
1175 return 0;
1176#elif defined(MIPS)
1177 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1178 return -1;
1179 return 0;
1180#elif defined(ALPHA)
1181 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1182 return -1;
1183 return 0;
1184#elif defined(AVR32)
1185 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1186 return -1;
1187 return 0;
1188#elif defined(BFIN)
1189 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1190 return -1;
1191 return 0;
1192#elif defined(IA64)
1193 if (ia32) {
1194 switch (new) {
1195 case 2:
1196 break; /* x86 SYS_fork */
1197 case SYS_clone:
1198 new = 120;
1199 break;
1200 default:
1201 fprintf(stderr, "%s: unexpected syscall %d\n",
1202 __FUNCTION__, new);
1203 return -1;
1204 }
1205 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1206 return -1;
1207 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1208 return -1;
1209 return 0;
1210#elif defined(HPPA)
1211 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1212 return -1;
1213 return 0;
1214#elif defined(SH)
1215 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1216 return -1;
1217 return 0;
1218#elif defined(SH64)
1219 /* Top half of reg encodes the no. of args n as 0x1n.
1220 Assume 0 args as kernel never actually checks... */
1221 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1222 0x100000 | new) < 0)
1223 return -1;
1224 return 0;
1225#elif defined(CRISV10) || defined(CRISV32)
1226 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1227 return -1;
1228 return 0;
1229#elif defined(ARM)
1230 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1231# ifndef PTRACE_SET_SYSCALL
1232# define PTRACE_SET_SYSCALL 23
1233# endif
1234 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1235 return -1;
1236 return 0;
1237#elif defined(TILE)
1238 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1239 (char*)PTREGS_OFFSET_REG(0),
1240 new) != 0)
1241 return -1;
1242 return 0;
1243#elif defined(MICROBLAZE)
1244 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1245 return -1;
1246 return 0;
1247#else
1248#warning Do not know how to handle change_syscall for this architecture
1249#endif /* architecture */
1250 return -1;
1251}
1252
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001253#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254
1255typedef unsigned long *arg_setup_state;
1256
1257static int
1258arg_setup(struct tcb *tcp, arg_setup_state *state)
1259{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001260 unsigned long cfm, sof, sol;
1261 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262
Jan Kratochvil1f942712008-08-06 21:38:52 +00001263 if (ia32) {
1264 /* Satisfy a false GCC warning. */
1265 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001266 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001267 }
Roland McGrath08267b82004-02-20 22:56:43 +00001268
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001269 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001271 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272 return -1;
1273
1274 sof = (cfm >> 0) & 0x7f;
1275 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001276 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277
Jan Kratochvil1f942712008-08-06 21:38:52 +00001278 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279 return 0;
1280}
1281
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001282# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001285get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286{
Roland McGrath08267b82004-02-20 22:56:43 +00001287 int ret;
1288
1289 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001290 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001291 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001292 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001293 (unsigned long) ia64_rse_skip_regs(*state, 0),
1294 sizeof(long), (void *) valp);
1295 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296}
1297
1298static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001299get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001300{
Roland McGrath08267b82004-02-20 22:56:43 +00001301 int ret;
1302
1303 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001304 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001305 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001306 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001307 (unsigned long) ia64_rse_skip_regs(*state, 1),
1308 sizeof(long), (void *) valp);
1309 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311
1312static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001313set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001314{
Roland McGrath08267b82004-02-20 22:56:43 +00001315 int req = PTRACE_POKEDATA;
1316 void *ap;
1317
1318 if (ia32) {
1319 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1320 req = PTRACE_POKEUSER;
1321 } else
1322 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001323 errno = 0;
1324 ptrace(req, tcp->pid, ap, val);
1325 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001326}
1327
1328static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001329set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330{
Roland McGrath08267b82004-02-20 22:56:43 +00001331 int req = PTRACE_POKEDATA;
1332 void *ap;
1333
1334 if (ia32) {
1335 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1336 req = PTRACE_POKEUSER;
1337 } else
1338 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001339 errno = 0;
1340 ptrace(req, tcp->pid, ap, val);
1341 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342}
1343
Roland McGrathb659f872008-07-18 01:19:36 +00001344/* ia64 does not return the input arguments from functions (and syscalls)
1345 according to ia64 RSE (Register Stack Engine) behavior. */
1346
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001347# define restore_arg0(tcp, state, val) ((void) (state), 0)
1348# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001349
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001350#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351
Mike Frysinger8566c502009-10-12 11:05:14 -04001352typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001353
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001354# define arg_setup(tcp, state) \
1355 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1356# define arg_finish_change(tcp, state) \
1357 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001359# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1360# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1361# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1362# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1363# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001364
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001365#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001367# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001368/* Note: this is only true for the `clone' system call, which handles
1369 arguments specially. We could as well say that its first two arguments
1370 are swapped relative to other architectures, but that would just be
1371 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001372# define arg0_offset PT_GPR3
1373# define arg1_offset PT_ORIGGPR2
1374# define restore_arg0(tcp, state, val) ((void) (state), 0)
1375# define restore_arg1(tcp, state, val) ((void) (state), 0)
1376# define arg0_index 1
1377# define arg1_index 0
1378# elif defined(ALPHA) || defined(MIPS)
1379# define arg0_offset REG_A0
1380# define arg1_offset (REG_A0+1)
1381# elif defined(AVR32)
1382# define arg0_offset (REG_R12)
1383# define arg1_offset (REG_R11)
1384# elif defined(POWERPC)
1385# define arg0_offset (sizeof(unsigned long)*PT_R3)
1386# define arg1_offset (sizeof(unsigned long)*PT_R4)
1387# define restore_arg0(tcp, state, val) ((void) (state), 0)
1388# elif defined(HPPA)
1389# define arg0_offset PT_GR26
1390# define arg1_offset (PT_GR26-4)
1391# elif defined(X86_64)
1392# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1393# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1394# elif defined(SH)
1395# define arg0_offset (4*(REG_REG0+4))
1396# define arg1_offset (4*(REG_REG0+5))
1397# elif defined(SH64)
1398 /* ABI defines arg0 & 1 in r2 & r3 */
1399# define arg0_offset (REG_OFFSET+16)
1400# define arg1_offset (REG_OFFSET+24)
1401# define restore_arg0(tcp, state, val) 0
1402# elif defined CRISV10 || defined CRISV32
1403# define arg0_offset (4*PT_R11)
1404# define arg1_offset (4*PT_ORIG_R10)
1405# define restore_arg0(tcp, state, val) 0
1406# define restore_arg1(tcp, state, val) 0
1407# define arg0_index 1
1408# define arg1_index 0
1409# else
1410# define arg0_offset 0
1411# define arg1_offset 4
1412# if defined ARM
1413# define restore_arg0(tcp, state, val) 0
1414# endif
1415# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001416
1417typedef int arg_setup_state;
1418
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001419# define arg_setup(tcp, state) (0)
1420# define arg_finish_change(tcp, state) 0
1421# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1422# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423
1424static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001425set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001426{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001427 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001428}
1429
1430static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001431set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001432{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001433 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001434}
1435
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001436#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001438#ifndef restore_arg0
1439# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1440#endif
1441#ifndef restore_arg1
1442# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1443#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001445#ifndef arg0_index
1446# define arg0_index 0
1447# define arg1_index 1
1448#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001449
Roland McGrathd81f1d92003-01-09 06:53:34 +00001450int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001451setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001452{
Roland McGrath3291ef22008-05-20 00:34:34 +00001453 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001454 arg_setup_state state;
1455
1456 if (tcp->flags & TCB_BPTSET) {
1457 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1458 return -1;
1459 }
1460
Roland McGrath3291ef22008-05-20 00:34:34 +00001461 /*
1462 * It's a silly kludge to initialize this with a search at runtime.
1463 * But it's better than maintaining another magic thing in the
1464 * godforsaken tables.
1465 */
1466 if (clone_scno[current_personality] == 0) {
1467 int i;
1468 for (i = 0; i < nsyscalls; ++i)
1469 if (sysent[i].sys_func == sys_clone) {
1470 clone_scno[current_personality] = i;
1471 break;
1472 }
1473 }
1474
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001475 if (sysent[tcp->scno].sys_func == sys_fork ||
1476 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001477 if (arg_setup(tcp, &state) < 0
1478 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1479 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001480 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001481 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1482 || set_arg1(tcp, &state, 0) < 0
1483 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001485 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1486 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001487 tcp->flags |= TCB_BPTSET;
1488 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001489 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001490
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001491 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001492 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001493 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001494 vfork semantics into plain fork - each application must not
1495 depend on the vfork specifics according to POSIX. We would
1496 hang waiting for the parent resume otherwise. We need to
1497 clear also CLONE_VM but only in the CLONE_VFORK case as
1498 otherwise we would break pthread_create. */
1499
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001500 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1501 if (new_arg0 & CLONE_VFORK)
1502 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1503 if (arg_setup(tcp, &state) < 0
1504 || set_arg0(tcp, &state, new_arg0) < 0
1505 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001506 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001507 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001508 tcp->inst[0] = tcp->u_arg[arg0_index];
1509 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001510 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001511 }
1512
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001513 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1514 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001515 return -1;
1516}
1517
1518int
Denys Vlasenko12014262011-05-30 14:00:14 +02001519clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001520{
1521 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001522 if (arg_setup(tcp, &state) < 0
1523 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1524 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1525 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001526 if (errno != ESRCH)
1527 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001528 tcp->flags &= ~TCB_BPTSET;
1529 return 0;
1530}