blob: 33e4288f6029c1c2bedfe35574df010417fddecf [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.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
38#include <sys/user.h>
39#include <sys/param.h>
40#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000041#if HAVE_SYS_UIO_H
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010042# include <sys/uio.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000044
Denys Vlasenko84703742012-02-25 02:38:52 +010045#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
Wichert Akkerman36915a11999-07-13 15:45:02 +000046#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000047#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000048
Denys Vlasenko84703742012-02-25 02:38:52 +010049#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000050# include <asm/ptrace_offsets.h>
51# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000052#endif
53
Wichert Akkerman36915a11999-07-13 15:45:02 +000054#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010055# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000056# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000057#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010058# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000059# ifdef HAVE_STRUCT_IA64_FPREG
60# define ia64_fpreg XXX_ia64_fpreg
61# endif
62# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
63# define pt_all_user_regs XXX_pt_all_user_regs
64# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010065# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000066# undef ia64_fpreg
67# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000068#endif
69
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010070#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000071# undef PTRACE_GETREGS
72# define PTRACE_GETREGS PTRACE_GETREGS64
73# undef PTRACE_SETREGS
74# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077/* macros */
78#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010079# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#endif
81#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010082# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083#endif
84
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085int
Denys Vlasenko12014262011-05-30 14:00:14 +020086tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087{
88 return a->tv_sec || a->tv_usec;
89}
90
91int
Denys Vlasenko12014262011-05-30 14:00:14 +020092tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000093{
94 if (a->tv_sec < b->tv_sec
95 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
96 return -1;
97 if (a->tv_sec > b->tv_sec
98 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
99 return 1;
100 return 0;
101}
102
103double
Denys Vlasenko12014262011-05-30 14:00:14 +0200104tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105{
106 return tv->tv_sec + tv->tv_usec/1000000.0;
107}
108
109void
Denys Vlasenko12014262011-05-30 14:00:14 +0200110tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111{
112 tv->tv_sec = a->tv_sec + b->tv_sec;
113 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000114 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115 tv->tv_sec++;
116 tv->tv_usec -= 1000000;
117 }
118}
119
120void
Denys Vlasenko12014262011-05-30 14:00:14 +0200121tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122{
123 tv->tv_sec = a->tv_sec - b->tv_sec;
124 tv->tv_usec = a->tv_usec - b->tv_usec;
125 if (((long) tv->tv_usec) < 0) {
126 tv->tv_sec--;
127 tv->tv_usec += 1000000;
128 }
129}
130
131void
Denys Vlasenko12014262011-05-30 14:00:14 +0200132tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133{
134 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
135 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
136 tv->tv_usec %= 1000000;
137}
138
139void
Denys Vlasenko12014262011-05-30 14:00:14 +0200140tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141{
142 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000143 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144 tv->tv_usec %= 1000000;
145}
146
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000147const char *
148xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149{
150 for (; xlat->str != NULL; xlat++)
151 if (xlat->val == val)
152 return xlat->str;
153 return NULL;
154}
155
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200156#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200157char *
158stpcpy(char *dst, const char *src)
159{
160 while ((*dst = *src++) != '\0')
161 dst++;
162 return dst;
163}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200164#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200165
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166/*
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000167 * Used when we want to unblock stopped traced process.
168 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
169 * Returns 0 on success or if error was ESRCH
170 * (presumably process was killed while we talk to it).
171 * Otherwise prints error message and returns -1.
172 */
173int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700174ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000175{
176 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700177 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000178
179 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100180 ptrace(op, tcp->pid, (void *) 0, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000181 err = errno;
182 if (!err || err == ESRCH)
183 return 0;
184
185 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700186 msg = "SYSCALL";
187 if (op == PTRACE_CONT)
188 msg = "CONT";
189 if (op == PTRACE_DETACH)
190 msg = "DETACH";
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100191#ifdef PTRACE_LISTEN
192 if (op == PTRACE_LISTEN)
193 msg = "LISTEN";
194#endif
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100195 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000196 return -1;
197}
198
199/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 * Print entry in struct xlat table, if there.
201 */
202void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000203printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000205 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206
207 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200208 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209 else
210 tprintf("%#x /* %s */", val, dflt);
211}
212
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100213#if HAVE_LONG_LONG
214/*
215 * Print 64bit argument at position llarg and return the index of the next
216 * argument.
217 */
218int
219printllval(struct tcb *tcp, const char *format, int llarg)
220{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100221# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100222 if (current_personality == 0) {
223 tprintf(format, tcp->u_arg[llarg]);
224 llarg++;
225 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200226# ifdef POWERPC64
227 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200228 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200229# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100230 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
231 llarg += 2;
232 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200233# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100234 tprintf(format, tcp->u_arg[llarg]);
235 llarg++;
236# elif defined LINUX_MIPSN32
237 tprintf(format, tcp->ext_arg[llarg]);
238 llarg++;
239# else
240 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
241 llarg += 2;
242# endif
243 return llarg;
244}
245#endif
246
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000247/*
248 * Interpret `xlat' as an array of flags
249 * print the entries whose bits are on in `flags'
250 * return # of flags printed.
251 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200252void
Denys Vlasenko12014262011-05-30 14:00:14 +0200253addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000254{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200255 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 if (xlat->val && (flags & xlat->val) == xlat->val) {
257 tprintf("|%s", xlat->str);
258 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000259 }
260 }
261 if (flags) {
262 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000263 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000264}
265
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000266/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200267 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000268 * Print to static string the entries whose bits are on in `flags'
269 * Return static string.
270 */
271const char *
272sprintflags(const char *prefix, const struct xlat *xlat, int flags)
273{
274 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200275 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000276 int found = 0;
277
Denys Vlasenko52845572011-08-31 12:07:38 +0200278 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000279
280 for (; xlat->str; xlat++) {
281 if ((flags & xlat->val) == xlat->val) {
282 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200283 *outptr++ = '|';
284 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000285 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100286 flags &= ~xlat->val;
287 if (!flags)
288 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000289 }
290 }
291 if (flags) {
292 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200293 *outptr++ = '|';
294 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000295 }
296
297 return outstr;
298}
299
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000300int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000301printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302{
303 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000304 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000305
306 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200307 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308 return 1;
309 }
310
311 sep = "";
312 for (n = 0; xlat->str; xlat++) {
313 if (xlat->val && (flags & xlat->val) == xlat->val) {
314 tprintf("%s%s", sep, xlat->str);
315 flags &= ~xlat->val;
316 sep = "|";
317 n++;
318 }
319 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000320
321 if (n) {
322 if (flags) {
323 tprintf("%s%#x", sep, flags);
324 n++;
325 }
326 } else {
327 if (flags) {
328 tprintf("%#x", flags);
329 if (dflt)
330 tprintf(" /* %s */", dflt);
331 } else {
332 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200333 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000334 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000335 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337 return n;
338}
339
340void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000341printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000342{
Roland McGratheb285352003-01-14 09:59:00 +0000343 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000344
345 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200346 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000347 return;
348 }
349 if (umove(tcp, addr, &num) < 0) {
350 tprintf("%#lx", addr);
351 return;
352 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200353 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000354 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200355 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356}
357
Roland McGrath6bc12202003-11-13 22:32:27 +0000358void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000359printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000360{
361 int num;
362
363 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200364 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000365 return;
366 }
367 if (umove(tcp, addr, &num) < 0) {
368 tprintf("%#lx", addr);
369 return;
370 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200371 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000372 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200373 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000374}
375
376void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300377printfd(struct tcb *tcp, int fd)
378{
Grant Edwards8a082772011-04-07 20:25:40 +0000379 const char *p;
380
381 if (show_fd_path && (p = getfdpath(tcp, fd)))
382 tprintf("%d<%s>", fd, p);
383 else
384 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300385}
386
387void
Denys Vlasenko12014262011-05-30 14:00:14 +0200388printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000389{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200390 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000391}
392
Dmitry V. Levina501f142008-11-10 23:19:13 +0000393/*
394 * Quote string `instr' of length `size'
395 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
396 * If `len' < 0, treat `instr' as a NUL-terminated string
397 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100398 *
399 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
400 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000401 */
Roland McGrath6d970322007-11-01 23:53:59 +0000402static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000403string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000405 const unsigned char *ustr = (const unsigned char *) instr;
406 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200407 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200409 eol = 0x100; /* this can never match a char */
410 if (len < 0) {
411 size--;
412 eol = '\0';
413 }
414
415 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000416 if (xflag > 1)
417 usehex = 1;
418 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000419 /* Check for presence of symbol which require
420 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000421 for (i = 0; i < size; ++i) {
422 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000423 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200424 if (c == eol)
425 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000426 if (!isprint(c) && !isspace(c)) {
427 usehex = 1;
428 break;
429 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000430 }
431 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000432
433 *s++ = '\"';
434
435 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000436 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000437 for (i = 0; i < size; ++i) {
438 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000439 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200440 if (c == eol)
441 goto asciz_ended;
442 *s++ = '\\';
443 *s++ = 'x';
444 *s++ = "0123456789abcdef"[c >> 4];
445 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000446 }
447 } else {
448 for (i = 0; i < size; ++i) {
449 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000450 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200451 if (c == eol)
452 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000453 switch (c) {
454 case '\"': case '\\':
455 *s++ = '\\';
456 *s++ = c;
457 break;
458 case '\f':
459 *s++ = '\\';
460 *s++ = 'f';
461 break;
462 case '\n':
463 *s++ = '\\';
464 *s++ = 'n';
465 break;
466 case '\r':
467 *s++ = '\\';
468 *s++ = 'r';
469 break;
470 case '\t':
471 *s++ = '\\';
472 *s++ = 't';
473 break;
474 case '\v':
475 *s++ = '\\';
476 *s++ = 'v';
477 break;
478 default:
479 if (isprint(c))
480 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200481 else {
482 /* Print \octal */
483 *s++ = '\\';
484 if (i + 1 < size
485 && ustr[i + 1] >= '0'
486 && ustr[i + 1] <= '9'
487 ) {
488 /* Print \ooo */
489 *s++ = '0' + (c >> 6);
490 *s++ = '0' + ((c >> 3) & 0x7);
491 } else {
492 /* Print \[[o]o]o */
493 if ((c >> 3) != 0) {
494 if ((c >> 6) != 0)
495 *s++ = '0' + (c >> 6);
496 *s++ = '0' + ((c >> 3) & 0x7);
497 }
498 }
499 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000500 }
501 break;
502 }
503 }
504 }
505
506 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000508
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200509 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
510 if (len < 0 && ustr[i] == '\0') {
511 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
512 * but next char is NUL.
513 */
514 return 0;
515 }
516
517 return 1;
518
519 asciz_ended:
520 *s++ = '\"';
521 *s = '\0';
522 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
523 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524}
525
Dmitry V. Levina501f142008-11-10 23:19:13 +0000526/*
527 * Print path string specified by address `addr' and length `n'.
528 * If path length exceeds `n', append `...' to the output.
529 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000531printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100533 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100534 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100535
Dmitry V. Levina501f142008-11-10 23:19:13 +0000536 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200537 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000538 return;
539 }
540
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100541 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000542 if (n > sizeof path - 1)
543 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000544
545 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100546 nul_seen = umovestr(tcp, addr, n + 1, path);
547 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 tprintf("%#lx", addr);
549 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100550 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000551
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100552 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100553 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100554 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100555 string_quote(path, outstr, -1, n);
556 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100557 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100558 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559 }
560}
561
562void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000563printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100565 /* Size must correspond to char path[] size in printpathn */
566 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567}
568
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569/*
570 * Print string specified by address `addr' and length `len'.
571 * If `len' < 0, treat the string as a NUL-terminated string.
572 * If string length exceeds `max_strlen', append `...' to the output.
573 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574void
575printstr(struct tcb *tcp, long addr, int len)
576{
577 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000579 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100580 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581
582 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200583 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 return;
585 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000586 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200587 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000588 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200589 if (!str)
590 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100591 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200592 if (!outstr)
593 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000595
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000597 /*
598 * Treat as a NUL-terminated string: fetch one byte more
599 * because string_quote() quotes one byte less.
600 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000601 size = max_strlen + 1;
602 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000603 tprintf("%#lx", addr);
604 return;
605 }
606 }
607 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000608 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000609 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000610 tprintf("%#lx", addr);
611 return;
612 }
613 }
614
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100615 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
616 * or we were requested to print more than -s NUM chars)...
617 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100618 ellipsis = (string_quote(str, outstr, len, size) &&
619 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000620
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100621 tprints(outstr);
622 if (ellipsis)
623 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624}
625
John Hughes1d08dcf2001-07-10 13:48:44 +0000626#if HAVE_SYS_UIO_H
627void
Denys Vlasenko12014262011-05-30 14:00:14 +0200628dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000629{
Denys Vlasenko84703742012-02-25 02:38:52 +0100630#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000631 union {
632 struct { u_int32_t base; u_int32_t len; } *iov32;
633 struct { u_int64_t base; u_int64_t len; } *iov64;
634 } iovu;
635#define iov iovu.iov64
636#define sizeof_iov \
637 (personality_wordsize[current_personality] == 4 \
638 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
639#define iov_iov_base(i) \
640 (personality_wordsize[current_personality] == 4 \
641 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
642#define iov_iov_len(i) \
643 (personality_wordsize[current_personality] == 4 \
644 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
645#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000646 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000647#define sizeof_iov sizeof(*iov)
648#define iov_iov_base(i) iov[i].iov_base
649#define iov_iov_len(i) iov[i].iov_len
650#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000651 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200652 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000653
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200654 size = sizeof_iov * len;
655 /* Assuming no sane program has millions of iovs */
656 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000657 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200658 fprintf(stderr, "Out of memory\n");
659 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000660 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000661 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000662 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000663 /* include the buffer number to make it easy to
664 * match up the trace with the source */
665 tprintf(" * %lu bytes in buffer %d\n",
666 (unsigned long)iov_iov_len(i), i);
667 dumpstr(tcp, (long) iov_iov_base(i),
668 iov_iov_len(i));
669 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000670 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200671 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000672#undef sizeof_iov
673#undef iov_iov_base
674#undef iov_iov_len
675#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000676}
677#endif
678
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679void
Denys Vlasenko12014262011-05-30 14:00:14 +0200680dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681{
682 static int strsize = -1;
683 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 char *s;
685 int i, j;
686
687 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200688 free(str);
689 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200690 if (!str) {
691 strsize = -1;
692 fprintf(stderr, "Out of memory\n");
693 return;
694 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 strsize = len;
696 }
697
698 if (umoven(tcp, addr, len, (char *) str) < 0)
699 return;
700
701 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200702 char outstr[80];
703
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000704 s = outstr;
705 sprintf(s, " | %05x ", i);
706 s += 9;
707 for (j = 0; j < 16; j++) {
708 if (j == 8)
709 *s++ = ' ';
710 if (i + j < len) {
711 sprintf(s, " %02x", str[i + j]);
712 s += 3;
713 }
714 else {
715 *s++ = ' '; *s++ = ' '; *s++ = ' ';
716 }
717 }
718 *s++ = ' '; *s++ = ' ';
719 for (j = 0; j < 16; j++) {
720 if (j == 8)
721 *s++ = ' ';
722 if (i + j < len) {
723 if (isprint(str[i + j]))
724 *s++ = str[i + j];
725 else
726 *s++ = '.';
727 }
728 else
729 *s++ = ' ';
730 }
731 tprintf("%s |\n", outstr);
732 }
733}
734
Mike Frysinger612659e2012-02-14 14:38:28 +0100735#ifdef HAVE_PROCESS_VM_READV
736/* C library supports this, but the kernel might not. */
737static bool process_vm_readv_not_supported = 0;
738#else
739
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100740/* Need to do this since process_vm_readv() is not yet available in libc.
741 * When libc is be updated, only "static bool process_vm_readv_not_supported"
742 * line should remain.
743 */
744#if !defined(__NR_process_vm_readv)
745# if defined(I386)
746# define __NR_process_vm_readv 347
747# elif defined(X86_64)
748# define __NR_process_vm_readv 310
749# elif defined(POWERPC)
750# define __NR_process_vm_readv 351
751# endif
752#endif
753
754#if defined(__NR_process_vm_readv)
755static bool process_vm_readv_not_supported = 0;
756static ssize_t process_vm_readv(pid_t pid,
757 const struct iovec *lvec,
758 unsigned long liovcnt,
759 const struct iovec *rvec,
760 unsigned long riovcnt,
761 unsigned long flags)
762{
763 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
764}
765#else
766static bool process_vm_readv_not_supported = 1;
767# define process_vm_readv(...) (errno = ENOSYS, -1)
768#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100769
770#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100771
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772#define PAGMASK (~(PAGSIZ - 1))
773/*
774 * move `len' bytes of data from process `pid'
775 * at address `addr' to our space at `laddr'
776 */
777int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000778umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700780 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100782 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 union {
784 long val;
785 char x[sizeof(long)];
786 } u;
787
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100788#if SUPPORTED_PERSONALITIES > 1
789 if (personality_wordsize[current_personality] < sizeof(addr))
790 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
791#endif
792
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100793 if (!process_vm_readv_not_supported) {
794 struct iovec local[1], remote[1];
795 int r;
796
797 local[0].iov_base = laddr;
798 remote[0].iov_base = (void*)addr;
799 local[0].iov_len = remote[0].iov_len = len;
800 r = process_vm_readv(pid,
801 local, 1,
802 remote, 1,
803 /*flags:*/ 0
804 );
805 if (r < 0) {
806 if (errno == ENOSYS)
807 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100808 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
809 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100810 perror("process_vm_readv");
811 goto vm_readv_didnt_work;
812 }
813 return r;
814 }
815 vm_readv_didnt_work:
816
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100817 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000818 if (addr & (sizeof(long) - 1)) {
819 /* addr not a multiple of sizeof(long) */
820 n = addr - (addr & -sizeof(long)); /* residue */
821 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700822 errno = 0;
823 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
824 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700825 /* But if not started, we had a bogus address. */
826 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100827 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700828 return -1;
829 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000830 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100831 m = MIN(sizeof(long) - n, len);
832 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000833 addr += sizeof(long), laddr += m, len -= m;
834 }
835 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700836 errno = 0;
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
838 if (errno) {
839 if (started && (errno==EPERM || errno==EIO)) {
840 /* Ran into 'end of memory' - stupid "printpath" */
841 return 0;
842 }
843 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100844 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700845 return -1;
846 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000847 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100848 m = MIN(sizeof(long), len);
849 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 addr += sizeof(long), laddr += m, len -= m;
851 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853 return 0;
854}
855
856/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100857 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100859 *
860 * Returns < 0 on error, > 0 if NUL was seen,
861 * (TODO if useful: return count of bytes including NUL),
862 * else 0 if len bytes were read but no NUL byte seen.
863 *
864 * Note: there is no guarantee we won't overwrite some bytes
865 * in laddr[] _after_ terminating NUL (but, of course,
866 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867 */
868int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000869umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100871 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700872 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873 int i, n, m;
874 union {
875 long val;
876 char x[sizeof(long)];
877 } u;
878
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000879#if SUPPORTED_PERSONALITIES > 1
880 if (personality_wordsize[current_personality] < sizeof(addr))
881 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
882#endif
883
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100884 if (!process_vm_readv_not_supported) {
885 struct iovec local[1], remote[1];
886
887 local[0].iov_base = laddr;
888 remote[0].iov_base = (void*)addr;
889
890 while (len > 0) {
891 int end_in_page;
892 int r;
893 int chunk_len;
894
895 /* Don't read kilobytes: most strings are short */
896 chunk_len = len;
897 if (chunk_len > 256)
898 chunk_len = 256;
899 /* Don't cross pages. I guess otherwise we can get EFAULT
900 * and fail to notice that terminating NUL lies
901 * in the existing (first) page.
902 * (I hope there aren't arches with pages < 4K)
903 */
904 end_in_page = ((addr + chunk_len) & 4095);
905 r = chunk_len - end_in_page;
906 if (r > 0) /* if chunk_len > end_in_page */
907 chunk_len = r; /* chunk_len -= end_in_page */
908
909 local[0].iov_len = remote[0].iov_len = chunk_len;
910 r = process_vm_readv(pid,
911 local, 1,
912 remote, 1,
913 /*flags:*/ 0
914 );
915 if (r < 0) {
916 if (errno == ENOSYS)
917 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100918 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
919 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100920 perror("process_vm_readv");
921 goto vm_readv_didnt_work;
922 }
923 if (memchr(local[0].iov_base, '\0', r))
924 return 1;
925 local[0].iov_base += r;
926 remote[0].iov_base += r;
927 len -= r;
928 }
929 return 0;
930 }
931 vm_readv_didnt_work:
932
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100933 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934 if (addr & (sizeof(long) - 1)) {
935 /* addr not a multiple of sizeof(long) */
936 n = addr - (addr & -sizeof(long)); /* residue */
937 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700938 errno = 0;
939 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
940 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700941 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) - n, len);
947 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 while (n & (sizeof(long) - 1))
949 if (u.x[n++] == '\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 }
953 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700954 errno = 0;
955 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
956 if (errno) {
957 if (started && (errno==EPERM || errno==EIO)) {
958 /* Ran into 'end of memory' - stupid "printpath" */
959 return 0;
960 }
961 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100962 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700963 return -1;
964 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000965 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100966 m = MIN(sizeof(long), len);
967 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 for (i = 0; i < sizeof(long); i++)
969 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100970 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 addr += sizeof(long), laddr += m, len -= m;
972 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000973 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974}
975
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100976#if !defined(SPARC) && !defined(SPARC64)
977# define PTRACE_WRITETEXT 101
978# define PTRACE_WRITEDATA 102
979#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980
981int
Denys Vlasenko12014262011-05-30 14:00:14 +0200982upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983{
984 long val;
985
Roland McGratheb9e2e82009-06-02 16:49:22 -0700986 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100987 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700988 if (val == -1 && errno) {
989 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100990 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700991 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700993 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 *res = val;
995 return 0;
996}
997
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000999printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000{
Roland McGrath7a918832005-02-02 20:55:23 +00001001#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1002 sizeof(long) == 8 ? "[????????????????] " : \
1003 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001005#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 long eip;
1007
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001008 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001009 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 return;
1011 }
1012 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001013
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001014#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001015 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001016 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001017 PRINTBADPC;
1018 return;
1019 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001020# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001021 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001022# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001023 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001024# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001025
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001026#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001027 long rip;
1028
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001029 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001030 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001031 return;
1032 }
1033 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001034#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001035 long ip;
1036
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001037 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001038 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001039 return;
1040 }
1041 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001042#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 long pc;
1044
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001045 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001046 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 return;
1048 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001049# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001050 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001051# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001053# endif
1054#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 long pc;
1056
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001057 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001058 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 return;
1060 }
1061 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001062#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063 long pc;
1064
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001065 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001066 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001067 return;
1068 }
1069 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001070#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001071 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001072 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001073 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 return;
1075 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001076# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001077 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001078# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001079 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001080# endif
1081#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001082 long pc;
1083
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001084 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001085 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001086 return;
1087 }
1088 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001089#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001090 long pc;
1091
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001092 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001093 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001094 return;
1095 }
1096 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001097#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001098 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001099
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001100 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001101 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001102 return;
1103 }
1104 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001105#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001106 long pc;
1107
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001108 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001109 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001110 return;
1111 }
1112 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001113#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001114 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001115
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001116 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001117 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001118 return;
1119 }
1120 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001121#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001122 long pc;
1123
1124 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001125 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001126 return;
1127 }
1128 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001129#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001130 long pc;
1131
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001132 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001133 PRINTBADPC;
1134 return;
1135 }
1136 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001137#elif defined(CRISV10)
1138 long pc;
1139
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001140 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001141 PRINTBADPC;
1142 return;
1143 }
1144 tprintf("[%08lx] ", pc);
1145#elif defined(CRISV32)
1146 long pc;
1147
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001148 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001149 PRINTBADPC;
1150 return;
1151 }
1152 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001153#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154}
1155
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001156/*
1157 * These #if's are huge, please indent them correctly.
1158 * It's easy to get confused otherwise.
1159 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001161#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001162
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001163#ifndef CLONE_PTRACE
1164# define CLONE_PTRACE 0x00002000
1165#endif
1166#ifndef CLONE_VFORK
1167# define CLONE_VFORK 0x00004000
1168#endif
1169#ifndef CLONE_VM
1170# define CLONE_VM 0x00000100
1171#endif
1172#ifndef CLONE_STOPPED
1173# define CLONE_STOPPED 0x02000000
1174#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001175
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001176#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001177
1178typedef unsigned long *arg_setup_state;
1179
1180static int
1181arg_setup(struct tcb *tcp, arg_setup_state *state)
1182{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001183 unsigned long cfm, sof, sol;
1184 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001185
Jan Kratochvil1f942712008-08-06 21:38:52 +00001186 if (ia32) {
1187 /* Satisfy a false GCC warning. */
1188 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001189 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001190 }
Roland McGrath08267b82004-02-20 22:56:43 +00001191
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001192 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001193 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001194 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001195 return -1;
1196
1197 sof = (cfm >> 0) & 0x7f;
1198 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001199 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001200
Jan Kratochvil1f942712008-08-06 21:38:52 +00001201 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202 return 0;
1203}
1204
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001205# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206
Roland McGrathd81f1d92003-01-09 06:53:34 +00001207static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001208get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001209{
Roland McGrath08267b82004-02-20 22:56:43 +00001210 int ret;
1211
1212 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001213 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001214 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001215 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001216 (unsigned long) ia64_rse_skip_regs(*state, 0),
1217 sizeof(long), (void *) valp);
1218 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001219}
1220
1221static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001222get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001223{
Roland McGrath08267b82004-02-20 22:56:43 +00001224 int ret;
1225
1226 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001227 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001228 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001229 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001230 (unsigned long) ia64_rse_skip_regs(*state, 1),
1231 sizeof(long), (void *) valp);
1232 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001233}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001234
1235static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001236set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001237{
Roland McGrath08267b82004-02-20 22:56:43 +00001238 int req = PTRACE_POKEDATA;
1239 void *ap;
1240
1241 if (ia32) {
1242 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1243 req = PTRACE_POKEUSER;
1244 } else
1245 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001246 errno = 0;
1247 ptrace(req, tcp->pid, ap, val);
1248 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001249}
1250
1251static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001252set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001253{
Roland McGrath08267b82004-02-20 22:56:43 +00001254 int req = PTRACE_POKEDATA;
1255 void *ap;
1256
1257 if (ia32) {
1258 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1259 req = PTRACE_POKEUSER;
1260 } else
1261 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001262 errno = 0;
1263 ptrace(req, tcp->pid, ap, val);
1264 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265}
1266
Roland McGrathb659f872008-07-18 01:19:36 +00001267/* ia64 does not return the input arguments from functions (and syscalls)
1268 according to ia64 RSE (Register Stack Engine) behavior. */
1269
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001270# define restore_arg0(tcp, state, val) ((void) (state), 0)
1271# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001272
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001273#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001274
Mike Frysinger8566c502009-10-12 11:05:14 -04001275typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001276
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001277# define arg_setup(tcp, state) \
1278 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1279# define arg_finish_change(tcp, state) \
1280 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001282# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1283# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1284# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1285# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1286# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001288#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001289
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001290# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001291/* Note: this is only true for the `clone' system call, which handles
1292 arguments specially. We could as well say that its first two arguments
1293 are swapped relative to other architectures, but that would just be
1294 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001295# define arg0_offset PT_GPR3
1296# define arg1_offset PT_ORIGGPR2
1297# define restore_arg0(tcp, state, val) ((void) (state), 0)
1298# define restore_arg1(tcp, state, val) ((void) (state), 0)
1299# define arg0_index 1
1300# define arg1_index 0
1301# elif defined(ALPHA) || defined(MIPS)
1302# define arg0_offset REG_A0
1303# define arg1_offset (REG_A0+1)
1304# elif defined(AVR32)
1305# define arg0_offset (REG_R12)
1306# define arg1_offset (REG_R11)
1307# elif defined(POWERPC)
1308# define arg0_offset (sizeof(unsigned long)*PT_R3)
1309# define arg1_offset (sizeof(unsigned long)*PT_R4)
1310# define restore_arg0(tcp, state, val) ((void) (state), 0)
1311# elif defined(HPPA)
1312# define arg0_offset PT_GR26
1313# define arg1_offset (PT_GR26-4)
1314# elif defined(X86_64)
1315# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1316# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1317# elif defined(SH)
1318# define arg0_offset (4*(REG_REG0+4))
1319# define arg1_offset (4*(REG_REG0+5))
1320# elif defined(SH64)
1321 /* ABI defines arg0 & 1 in r2 & r3 */
1322# define arg0_offset (REG_OFFSET+16)
1323# define arg1_offset (REG_OFFSET+24)
1324# define restore_arg0(tcp, state, val) 0
1325# elif defined CRISV10 || defined CRISV32
1326# define arg0_offset (4*PT_R11)
1327# define arg1_offset (4*PT_ORIG_R10)
1328# define restore_arg0(tcp, state, val) 0
1329# define restore_arg1(tcp, state, val) 0
1330# define arg0_index 1
1331# define arg1_index 0
1332# else
1333# define arg0_offset 0
1334# define arg1_offset 4
1335# if defined ARM
1336# define restore_arg0(tcp, state, val) 0
1337# endif
1338# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339
1340typedef int arg_setup_state;
1341
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001342# define arg_setup(tcp, state) (0)
1343# define arg_finish_change(tcp, state) 0
1344# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1345# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001346
1347static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001348set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001350 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351}
1352
1353static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001354set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001356 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357}
1358
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001359#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001361#ifndef restore_arg0
1362# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1363#endif
1364#ifndef restore_arg1
1365# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1366#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001367
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001368#ifndef arg0_index
1369# define arg0_index 0
1370# define arg1_index 1
1371#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001372
Roland McGrathd81f1d92003-01-09 06:53:34 +00001373int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001374setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001375{
Roland McGrath3291ef22008-05-20 00:34:34 +00001376 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001377 arg_setup_state state;
1378
1379 if (tcp->flags & TCB_BPTSET) {
1380 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1381 return -1;
1382 }
1383
Roland McGrath3291ef22008-05-20 00:34:34 +00001384 /*
1385 * It's a silly kludge to initialize this with a search at runtime.
1386 * But it's better than maintaining another magic thing in the
1387 * godforsaken tables.
1388 */
1389 if (clone_scno[current_personality] == 0) {
1390 int i;
1391 for (i = 0; i < nsyscalls; ++i)
1392 if (sysent[i].sys_func == sys_clone) {
1393 clone_scno[current_personality] = i;
1394 break;
1395 }
1396 }
1397
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001398 if (sysent[tcp->scno].sys_func == sys_fork ||
1399 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001400 if (arg_setup(tcp, &state) < 0
1401 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1402 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001403 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001404 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1405 || set_arg1(tcp, &state, 0) < 0
1406 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001408 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1409 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001410 tcp->flags |= TCB_BPTSET;
1411 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001412 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001414 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001415 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001416 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001417 vfork semantics into plain fork - each application must not
1418 depend on the vfork specifics according to POSIX. We would
1419 hang waiting for the parent resume otherwise. We need to
1420 clear also CLONE_VM but only in the CLONE_VFORK case as
1421 otherwise we would break pthread_create. */
1422
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001423 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1424 if (new_arg0 & CLONE_VFORK)
1425 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1426 if (arg_setup(tcp, &state) < 0
1427 || set_arg0(tcp, &state, new_arg0) < 0
1428 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001429 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001430 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001431 tcp->inst[0] = tcp->u_arg[arg0_index];
1432 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001433 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001434 }
1435
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001436 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1437 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001438 return -1;
1439}
1440
1441int
Denys Vlasenko12014262011-05-30 14:00:14 +02001442clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001443{
1444 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 if (arg_setup(tcp, &state) < 0
1446 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1447 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1448 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001449 if (errno != ESRCH)
1450 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001451 tcp->flags &= ~TCB_BPTSET;
1452 return 0;
1453}