blob: 4066bcb599a5ab2a1ea773587cd8239b336812ea [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
Denys Vlasenko12014262011-05-30 14:00:14 +020083tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084{
85 return a->tv_sec || a->tv_usec;
86}
87
88int
Denys Vlasenko12014262011-05-30 14:00:14 +020089tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090{
91 if (a->tv_sec < b->tv_sec
92 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
93 return -1;
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 return 0;
98}
99
100double
Denys Vlasenko12014262011-05-30 14:00:14 +0200101tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102{
103 return tv->tv_sec + tv->tv_usec/1000000.0;
104}
105
106void
Denys Vlasenko12014262011-05-30 14:00:14 +0200107tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 tv->tv_sec = a->tv_sec + b->tv_sec;
110 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000111 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112 tv->tv_sec++;
113 tv->tv_usec -= 1000000;
114 }
115}
116
117void
Denys Vlasenko12014262011-05-30 14:00:14 +0200118tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119{
120 tv->tv_sec = a->tv_sec - b->tv_sec;
121 tv->tv_usec = a->tv_usec - b->tv_usec;
122 if (((long) tv->tv_usec) < 0) {
123 tv->tv_sec--;
124 tv->tv_usec += 1000000;
125 }
126}
127
128void
Denys Vlasenko12014262011-05-30 14:00:14 +0200129tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130{
131 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
132 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
133 tv->tv_usec %= 1000000;
134}
135
136void
Denys Vlasenko12014262011-05-30 14:00:14 +0200137tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138{
139 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000140 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141 tv->tv_usec %= 1000000;
142}
143
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000144const char *
145xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146{
147 for (; xlat->str != NULL; xlat++)
148 if (xlat->val == val)
149 return xlat->str;
150 return NULL;
151}
152
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200153#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200154char *
155stpcpy(char *dst, const char *src)
156{
157 while ((*dst = *src++) != '\0')
158 dst++;
159 return dst;
160}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200161#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163/*
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000164 * Used when we want to unblock stopped traced process.
165 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
166 * Returns 0 on success or if error was ESRCH
167 * (presumably process was killed while we talk to it).
168 * Otherwise prints error message and returns -1.
169 */
170int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700171ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000172{
173 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700174 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000175
176 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100177 ptrace(op, tcp->pid, (void *) 0, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000178 err = errno;
179 if (!err || err == ESRCH)
180 return 0;
181
182 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700183 msg = "SYSCALL";
184 if (op == PTRACE_CONT)
185 msg = "CONT";
186 if (op == PTRACE_DETACH)
187 msg = "DETACH";
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100188#ifdef PTRACE_LISTEN
189 if (op == PTRACE_LISTEN)
190 msg = "LISTEN";
191#endif
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100192 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000193 return -1;
194}
195
196/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197 * Print entry in struct xlat table, if there.
198 */
199void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000200printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000202 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203
204 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200205 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206 else
207 tprintf("%#x /* %s */", val, dflt);
208}
209
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100210#if HAVE_LONG_LONG
211/*
212 * Print 64bit argument at position llarg and return the index of the next
213 * argument.
214 */
215int
216printllval(struct tcb *tcp, const char *format, int llarg)
217{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100218# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100219 if (current_personality == 0) {
220 tprintf(format, tcp->u_arg[llarg]);
221 llarg++;
222 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200223# ifdef POWERPC64
224 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200225 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200226# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100227 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
228 llarg += 2;
229 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200230# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100231 tprintf(format, tcp->u_arg[llarg]);
232 llarg++;
233# elif defined LINUX_MIPSN32
234 tprintf(format, tcp->ext_arg[llarg]);
235 llarg++;
236# else
237 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
238 llarg += 2;
239# endif
240 return llarg;
241}
242#endif
243
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244/*
245 * Interpret `xlat' as an array of flags
246 * print the entries whose bits are on in `flags'
247 * return # of flags printed.
248 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200249void
Denys Vlasenko12014262011-05-30 14:00:14 +0200250addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200252 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253 if (xlat->val && (flags & xlat->val) == xlat->val) {
254 tprintf("|%s", xlat->str);
255 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 }
257 }
258 if (flags) {
259 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000260 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000261}
262
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000263/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200264 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000265 * Print to static string the entries whose bits are on in `flags'
266 * Return static string.
267 */
268const char *
269sprintflags(const char *prefix, const struct xlat *xlat, int flags)
270{
271 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200272 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000273 int found = 0;
274
Denys Vlasenko52845572011-08-31 12:07:38 +0200275 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000276
277 for (; xlat->str; xlat++) {
278 if ((flags & xlat->val) == xlat->val) {
279 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200280 *outptr++ = '|';
281 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000282 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100283 flags &= ~xlat->val;
284 if (!flags)
285 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000286 }
287 }
288 if (flags) {
289 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200290 *outptr++ = '|';
291 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000292 }
293
294 return outstr;
295}
296
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000298printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299{
300 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000301 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302
303 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200304 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000305 return 1;
306 }
307
308 sep = "";
309 for (n = 0; xlat->str; xlat++) {
310 if (xlat->val && (flags & xlat->val) == xlat->val) {
311 tprintf("%s%s", sep, xlat->str);
312 flags &= ~xlat->val;
313 sep = "|";
314 n++;
315 }
316 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000317
318 if (n) {
319 if (flags) {
320 tprintf("%s%#x", sep, flags);
321 n++;
322 }
323 } else {
324 if (flags) {
325 tprintf("%#x", flags);
326 if (dflt)
327 tprintf(" /* %s */", dflt);
328 } else {
329 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200330 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000331 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000332 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000333
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000334 return n;
335}
336
337void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000338printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339{
Roland McGratheb285352003-01-14 09:59:00 +0000340 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000341
342 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200343 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +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("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000351 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200352 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353}
354
Roland McGrath6bc12202003-11-13 22:32:27 +0000355void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000356printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000357{
358 int num;
359
360 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200361 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000362 return;
363 }
364 if (umove(tcp, addr, &num) < 0) {
365 tprintf("%#lx", addr);
366 return;
367 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200368 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000369 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200370 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000371}
372
373void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300374printfd(struct tcb *tcp, int fd)
375{
Grant Edwards8a082772011-04-07 20:25:40 +0000376 const char *p;
377
378 if (show_fd_path && (p = getfdpath(tcp, fd)))
379 tprintf("%d<%s>", fd, p);
380 else
381 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300382}
383
384void
Denys Vlasenko12014262011-05-30 14:00:14 +0200385printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000386{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200387 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000388}
389
Dmitry V. Levina501f142008-11-10 23:19:13 +0000390/*
391 * Quote string `instr' of length `size'
392 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
393 * If `len' < 0, treat `instr' as a NUL-terminated string
394 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100395 *
396 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
397 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000398 */
Roland McGrath6d970322007-11-01 23:53:59 +0000399static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000400string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000401{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000402 const unsigned char *ustr = (const unsigned char *) instr;
403 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200404 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200406 eol = 0x100; /* this can never match a char */
407 if (len < 0) {
408 size--;
409 eol = '\0';
410 }
411
412 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000413 if (xflag > 1)
414 usehex = 1;
415 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000416 /* Check for presence of symbol which require
417 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000418 for (i = 0; i < size; ++i) {
419 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000420 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200421 if (c == eol)
422 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423 if (!isprint(c) && !isspace(c)) {
424 usehex = 1;
425 break;
426 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427 }
428 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000429
430 *s++ = '\"';
431
432 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000433 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000434 for (i = 0; i < size; ++i) {
435 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000436 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200437 if (c == eol)
438 goto asciz_ended;
439 *s++ = '\\';
440 *s++ = 'x';
441 *s++ = "0123456789abcdef"[c >> 4];
442 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000443 }
444 } else {
445 for (i = 0; i < size; ++i) {
446 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000447 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200448 if (c == eol)
449 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000450 switch (c) {
451 case '\"': case '\\':
452 *s++ = '\\';
453 *s++ = c;
454 break;
455 case '\f':
456 *s++ = '\\';
457 *s++ = 'f';
458 break;
459 case '\n':
460 *s++ = '\\';
461 *s++ = 'n';
462 break;
463 case '\r':
464 *s++ = '\\';
465 *s++ = 'r';
466 break;
467 case '\t':
468 *s++ = '\\';
469 *s++ = 't';
470 break;
471 case '\v':
472 *s++ = '\\';
473 *s++ = 'v';
474 break;
475 default:
476 if (isprint(c))
477 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200478 else {
479 /* Print \octal */
480 *s++ = '\\';
481 if (i + 1 < size
482 && ustr[i + 1] >= '0'
483 && ustr[i + 1] <= '9'
484 ) {
485 /* Print \ooo */
486 *s++ = '0' + (c >> 6);
487 *s++ = '0' + ((c >> 3) & 0x7);
488 } else {
489 /* Print \[[o]o]o */
490 if ((c >> 3) != 0) {
491 if ((c >> 6) != 0)
492 *s++ = '0' + (c >> 6);
493 *s++ = '0' + ((c >> 3) & 0x7);
494 }
495 }
496 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000497 }
498 break;
499 }
500 }
501 }
502
503 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000505
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200506 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
507 if (len < 0 && ustr[i] == '\0') {
508 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
509 * but next char is NUL.
510 */
511 return 0;
512 }
513
514 return 1;
515
516 asciz_ended:
517 *s++ = '\"';
518 *s = '\0';
519 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
520 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521}
522
Dmitry V. Levina501f142008-11-10 23:19:13 +0000523/*
524 * Print path string specified by address `addr' and length `n'.
525 * If path length exceeds `n', append `...' to the output.
526 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000529{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100530 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100531 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100532
Dmitry V. Levina501f142008-11-10 23:19:13 +0000533 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200534 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000535 return;
536 }
537
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100538 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000539 if (n > sizeof path - 1)
540 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000541
542 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100543 nul_seen = umovestr(tcp, addr, n + 1, path);
544 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 tprintf("%#lx", addr);
546 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100547 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000548
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100549 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100550 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100551 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100552 string_quote(path, outstr, -1, n);
553 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100554 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100555 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556 }
557}
558
559void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000560printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100562 /* Size must correspond to char path[] size in printpathn */
563 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000564}
565
Dmitry V. Levina501f142008-11-10 23:19:13 +0000566/*
567 * Print string specified by address `addr' and length `len'.
568 * If `len' < 0, treat the string as a NUL-terminated string.
569 * If string length exceeds `max_strlen', append `...' to the output.
570 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000571void
572printstr(struct tcb *tcp, long addr, int len)
573{
574 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000576 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100577 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578
579 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200580 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581 return;
582 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000583 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200584 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000585 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200586 if (!str)
587 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100588 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200589 if (!outstr)
590 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000592
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000594 /*
595 * Treat as a NUL-terminated string: fetch one byte more
596 * because string_quote() quotes one byte less.
597 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000598 size = max_strlen + 1;
599 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600 tprintf("%#lx", addr);
601 return;
602 }
603 }
604 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000605 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000606 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 tprintf("%#lx", addr);
608 return;
609 }
610 }
611
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100612 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
613 * or we were requested to print more than -s NUM chars)...
614 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100615 ellipsis = (string_quote(str, outstr, len, size) &&
616 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000617
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100618 tprints(outstr);
619 if (ellipsis)
620 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000621}
622
John Hughes1d08dcf2001-07-10 13:48:44 +0000623#if HAVE_SYS_UIO_H
624void
Denys Vlasenko12014262011-05-30 14:00:14 +0200625dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000626{
Denys Vlasenko84703742012-02-25 02:38:52 +0100627#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000628 union {
629 struct { u_int32_t base; u_int32_t len; } *iov32;
630 struct { u_int64_t base; u_int64_t len; } *iov64;
631 } iovu;
632#define iov iovu.iov64
633#define sizeof_iov \
634 (personality_wordsize[current_personality] == 4 \
635 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
636#define iov_iov_base(i) \
637 (personality_wordsize[current_personality] == 4 \
638 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
639#define iov_iov_len(i) \
640 (personality_wordsize[current_personality] == 4 \
641 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
642#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000643 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000644#define sizeof_iov sizeof(*iov)
645#define iov_iov_base(i) iov[i].iov_base
646#define iov_iov_len(i) iov[i].iov_len
647#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000648 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200649 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000650
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200651 size = sizeof_iov * len;
652 /* Assuming no sane program has millions of iovs */
653 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000654 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200655 fprintf(stderr, "Out of memory\n");
656 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000657 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000658 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000659 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000660 /* include the buffer number to make it easy to
661 * match up the trace with the source */
662 tprintf(" * %lu bytes in buffer %d\n",
663 (unsigned long)iov_iov_len(i), i);
664 dumpstr(tcp, (long) iov_iov_base(i),
665 iov_iov_len(i));
666 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000667 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200668 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000669#undef sizeof_iov
670#undef iov_iov_base
671#undef iov_iov_len
672#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000673}
674#endif
675
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676void
Denys Vlasenko12014262011-05-30 14:00:14 +0200677dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678{
679 static int strsize = -1;
680 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681 char *s;
682 int i, j;
683
684 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200685 free(str);
686 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200687 if (!str) {
688 strsize = -1;
689 fprintf(stderr, "Out of memory\n");
690 return;
691 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 strsize = len;
693 }
694
695 if (umoven(tcp, addr, len, (char *) str) < 0)
696 return;
697
698 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200699 char outstr[80];
700
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701 s = outstr;
702 sprintf(s, " | %05x ", i);
703 s += 9;
704 for (j = 0; j < 16; j++) {
705 if (j == 8)
706 *s++ = ' ';
707 if (i + j < len) {
708 sprintf(s, " %02x", str[i + j]);
709 s += 3;
710 }
711 else {
712 *s++ = ' '; *s++ = ' '; *s++ = ' ';
713 }
714 }
715 *s++ = ' '; *s++ = ' ';
716 for (j = 0; j < 16; j++) {
717 if (j == 8)
718 *s++ = ' ';
719 if (i + j < len) {
720 if (isprint(str[i + j]))
721 *s++ = str[i + j];
722 else
723 *s++ = '.';
724 }
725 else
726 *s++ = ' ';
727 }
728 tprintf("%s |\n", outstr);
729 }
730}
731
Mike Frysinger612659e2012-02-14 14:38:28 +0100732#ifdef HAVE_PROCESS_VM_READV
733/* C library supports this, but the kernel might not. */
734static bool process_vm_readv_not_supported = 0;
735#else
736
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100737/* Need to do this since process_vm_readv() is not yet available in libc.
738 * When libc is be updated, only "static bool process_vm_readv_not_supported"
739 * line should remain.
740 */
741#if !defined(__NR_process_vm_readv)
742# if defined(I386)
743# define __NR_process_vm_readv 347
744# elif defined(X86_64)
745# define __NR_process_vm_readv 310
746# elif defined(POWERPC)
747# define __NR_process_vm_readv 351
748# endif
749#endif
750
751#if defined(__NR_process_vm_readv)
752static bool process_vm_readv_not_supported = 0;
753static ssize_t process_vm_readv(pid_t pid,
754 const struct iovec *lvec,
755 unsigned long liovcnt,
756 const struct iovec *rvec,
757 unsigned long riovcnt,
758 unsigned long flags)
759{
760 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
761}
762#else
763static bool process_vm_readv_not_supported = 1;
764# define process_vm_readv(...) (errno = ENOSYS, -1)
765#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100766
767#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100768
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000769#define PAGMASK (~(PAGSIZ - 1))
770/*
771 * move `len' bytes of data from process `pid'
772 * at address `addr' to our space at `laddr'
773 */
774int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000775umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700777 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100779 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 union {
781 long val;
782 char x[sizeof(long)];
783 } u;
784
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100785#if SUPPORTED_PERSONALITIES > 1
786 if (personality_wordsize[current_personality] < sizeof(addr))
787 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
788#endif
789
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100790 if (!process_vm_readv_not_supported) {
791 struct iovec local[1], remote[1];
792 int r;
793
794 local[0].iov_base = laddr;
795 remote[0].iov_base = (void*)addr;
796 local[0].iov_len = remote[0].iov_len = len;
797 r = process_vm_readv(pid,
798 local, 1,
799 remote, 1,
800 /*flags:*/ 0
801 );
802 if (r < 0) {
803 if (errno == ENOSYS)
804 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100805 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
806 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100807 perror("process_vm_readv");
808 goto vm_readv_didnt_work;
809 }
810 return r;
811 }
812 vm_readv_didnt_work:
813
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100814 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 if (addr & (sizeof(long) - 1)) {
816 /* addr not a multiple of sizeof(long) */
817 n = addr - (addr & -sizeof(long)); /* residue */
818 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700819 errno = 0;
820 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
821 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700822 /* But if not started, we had a bogus address. */
823 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100824 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700825 return -1;
826 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000827 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100828 m = MIN(sizeof(long) - n, len);
829 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830 addr += sizeof(long), laddr += m, len -= m;
831 }
832 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700833 errno = 0;
834 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
835 if (errno) {
836 if (started && (errno==EPERM || errno==EIO)) {
837 /* Ran into 'end of memory' - stupid "printpath" */
838 return 0;
839 }
840 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100841 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700842 return -1;
843 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000844 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100845 m = MIN(sizeof(long), len);
846 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 addr += sizeof(long), laddr += m, len -= m;
848 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000849
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 return 0;
851}
852
853/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100854 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000855 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100856 *
857 * Returns < 0 on error, > 0 if NUL was seen,
858 * (TODO if useful: return count of bytes including NUL),
859 * else 0 if len bytes were read but no NUL byte seen.
860 *
861 * Note: there is no guarantee we won't overwrite some bytes
862 * in laddr[] _after_ terminating NUL (but, of course,
863 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 */
865int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000866umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100868 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700869 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870 int i, n, m;
871 union {
872 long val;
873 char x[sizeof(long)];
874 } u;
875
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000876#if SUPPORTED_PERSONALITIES > 1
877 if (personality_wordsize[current_personality] < sizeof(addr))
878 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
879#endif
880
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100881 if (!process_vm_readv_not_supported) {
882 struct iovec local[1], remote[1];
883
884 local[0].iov_base = laddr;
885 remote[0].iov_base = (void*)addr;
886
887 while (len > 0) {
888 int end_in_page;
889 int r;
890 int chunk_len;
891
892 /* Don't read kilobytes: most strings are short */
893 chunk_len = len;
894 if (chunk_len > 256)
895 chunk_len = 256;
896 /* Don't cross pages. I guess otherwise we can get EFAULT
897 * and fail to notice that terminating NUL lies
898 * in the existing (first) page.
899 * (I hope there aren't arches with pages < 4K)
900 */
901 end_in_page = ((addr + chunk_len) & 4095);
902 r = chunk_len - end_in_page;
903 if (r > 0) /* if chunk_len > end_in_page */
904 chunk_len = r; /* chunk_len -= end_in_page */
905
906 local[0].iov_len = remote[0].iov_len = chunk_len;
907 r = process_vm_readv(pid,
908 local, 1,
909 remote, 1,
910 /*flags:*/ 0
911 );
912 if (r < 0) {
913 if (errno == ENOSYS)
914 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100915 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
916 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100917 perror("process_vm_readv");
918 goto vm_readv_didnt_work;
919 }
920 if (memchr(local[0].iov_base, '\0', r))
921 return 1;
922 local[0].iov_base += r;
923 remote[0].iov_base += r;
924 len -= r;
925 }
926 return 0;
927 }
928 vm_readv_didnt_work:
929
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100930 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 if (addr & (sizeof(long) - 1)) {
932 /* addr not a multiple of sizeof(long) */
933 n = addr - (addr & -sizeof(long)); /* residue */
934 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700935 errno = 0;
936 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
937 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700938 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100939 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700940 return -1;
941 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000942 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100943 m = MIN(sizeof(long) - n, len);
944 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 while (n & (sizeof(long) - 1))
946 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100947 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 addr += sizeof(long), laddr += m, len -= m;
949 }
950 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700951 errno = 0;
952 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
953 if (errno) {
954 if (started && (errno==EPERM || errno==EIO)) {
955 /* Ran into 'end of memory' - stupid "printpath" */
956 return 0;
957 }
958 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100959 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700960 return -1;
961 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000962 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100963 m = MIN(sizeof(long), len);
964 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 for (i = 0; i < sizeof(long); i++)
966 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100967 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 addr += sizeof(long), laddr += m, len -= m;
969 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000970 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971}
972
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973int
Denys Vlasenko12014262011-05-30 14:00:14 +0200974upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975{
976 long val;
977
Roland McGratheb9e2e82009-06-02 16:49:22 -0700978 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100979 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700980 if (val == -1 && errno) {
981 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100982 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700983 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700985 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 *res = val;
987 return 0;
988}
989
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000991printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992{
Roland McGrath7a918832005-02-02 20:55:23 +0000993#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
994 sizeof(long) == 8 ? "[????????????????] " : \
995 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100997#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 long eip;
999
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001000 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001001 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 return;
1003 }
1004 tprintf("[%08lx] ", eip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001005#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001006 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001007 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001008 PRINTBADPC;
1009 return;
1010 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001011# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001012 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001013# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001014 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001015# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001016
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001017#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001018 long rip;
1019
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001020 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001021 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001022 return;
1023 }
1024 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001025#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001026 long ip;
1027
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001028 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001029 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001030 return;
1031 }
1032 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001033#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 long pc;
1035
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001036 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001037 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 return;
1039 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001040# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001041 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001042# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001044# endif
1045#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 long pc;
1047
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001048 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001049 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 return;
1051 }
1052 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001053#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 long pc;
1055
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001056 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001057 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 return;
1059 }
1060 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001061#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001062 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001063 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001064 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 return;
1066 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001067# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001068 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001069# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001070 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001071# endif
1072#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001073 long pc;
1074
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001075 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001076 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001077 return;
1078 }
1079 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001080#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001081 long pc;
1082
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001083 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001084 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001085 return;
1086 }
1087 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001088#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001089 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001090
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001091 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001092 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001093 return;
1094 }
1095 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001096#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001097 long pc;
1098
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001099 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001100 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001101 return;
1102 }
1103 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001104#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001105 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001106
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001107 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001108 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001109 return;
1110 }
1111 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001112#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001113 long pc;
1114
1115 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001116 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001117 return;
1118 }
1119 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001120#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001121 long pc;
1122
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001123 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001124 PRINTBADPC;
1125 return;
1126 }
1127 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001128#elif defined(CRISV10)
1129 long pc;
1130
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001131 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001132 PRINTBADPC;
1133 return;
1134 }
1135 tprintf("[%08lx] ", pc);
1136#elif defined(CRISV32)
1137 long pc;
1138
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001139 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001140 PRINTBADPC;
1141 return;
1142 }
1143 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001144#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145}
1146
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001147/*
1148 * These #if's are huge, please indent them correctly.
1149 * It's easy to get confused otherwise.
1150 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001152#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001153
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001154#ifndef CLONE_PTRACE
1155# define CLONE_PTRACE 0x00002000
1156#endif
1157#ifndef CLONE_VFORK
1158# define CLONE_VFORK 0x00004000
1159#endif
1160#ifndef CLONE_VM
1161# define CLONE_VM 0x00000100
1162#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001163
Denys Vlasenko081533c2012-03-17 02:17:51 +01001164static int
1165change_syscall(struct tcb *tcp, int new)
1166{
1167#if defined(I386)
1168 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1169 return -1;
1170 return 0;
1171#elif defined(X86_64)
1172 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1173 return -1;
1174 return 0;
1175#elif defined(POWERPC)
1176 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1177 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1178 return -1;
1179 return 0;
1180#elif defined(S390) || defined(S390X)
1181 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1182 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1183 return -1;
1184 return 0;
1185#elif defined(M68K)
1186 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1187 return -1;
1188 return 0;
1189#elif defined(SPARC) || defined(SPARC64)
1190 struct pt_regs regs;
1191 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1192 return -1;
1193 regs.u_regs[U_REG_G1] = new;
1194 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1195 return -1;
1196 return 0;
1197#elif defined(MIPS)
1198 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1199 return -1;
1200 return 0;
1201#elif defined(ALPHA)
1202 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1203 return -1;
1204 return 0;
1205#elif defined(AVR32)
1206 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1207 return -1;
1208 return 0;
1209#elif defined(BFIN)
1210 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1211 return -1;
1212 return 0;
1213#elif defined(IA64)
1214 if (ia32) {
1215 switch (new) {
1216 case 2:
1217 break; /* x86 SYS_fork */
1218 case SYS_clone:
1219 new = 120;
1220 break;
1221 default:
1222 fprintf(stderr, "%s: unexpected syscall %d\n",
1223 __FUNCTION__, new);
1224 return -1;
1225 }
1226 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1227 return -1;
1228 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1229 return -1;
1230 return 0;
1231#elif defined(HPPA)
1232 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1233 return -1;
1234 return 0;
1235#elif defined(SH)
1236 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1237 return -1;
1238 return 0;
1239#elif defined(SH64)
1240 /* Top half of reg encodes the no. of args n as 0x1n.
1241 Assume 0 args as kernel never actually checks... */
1242 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1243 0x100000 | new) < 0)
1244 return -1;
1245 return 0;
1246#elif defined(CRISV10) || defined(CRISV32)
1247 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1248 return -1;
1249 return 0;
1250#elif defined(ARM)
1251 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1252# ifndef PTRACE_SET_SYSCALL
1253# define PTRACE_SET_SYSCALL 23
1254# endif
1255 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1256 return -1;
1257 return 0;
1258#elif defined(TILE)
1259 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1260 (char*)PTREGS_OFFSET_REG(0),
1261 new) != 0)
1262 return -1;
1263 return 0;
1264#elif defined(MICROBLAZE)
1265 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1266 return -1;
1267 return 0;
1268#else
1269#warning Do not know how to handle change_syscall for this architecture
1270#endif /* architecture */
1271 return -1;
1272}
1273
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001274#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275
1276typedef unsigned long *arg_setup_state;
1277
1278static int
1279arg_setup(struct tcb *tcp, arg_setup_state *state)
1280{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001281 unsigned long cfm, sof, sol;
1282 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
Jan Kratochvil1f942712008-08-06 21:38:52 +00001284 if (ia32) {
1285 /* Satisfy a false GCC warning. */
1286 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001287 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001288 }
Roland McGrath08267b82004-02-20 22:56:43 +00001289
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001290 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001292 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001293 return -1;
1294
1295 sof = (cfm >> 0) & 0x7f;
1296 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001297 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001298
Jan Kratochvil1f942712008-08-06 21:38:52 +00001299 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001300 return 0;
1301}
1302
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001303# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304
Roland McGrathd81f1d92003-01-09 06:53:34 +00001305static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001306get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307{
Roland McGrath08267b82004-02-20 22:56:43 +00001308 int ret;
1309
1310 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001311 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001312 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001313 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001314 (unsigned long) ia64_rse_skip_regs(*state, 0),
1315 sizeof(long), (void *) valp);
1316 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317}
1318
1319static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001320get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001321{
Roland McGrath08267b82004-02-20 22:56:43 +00001322 int ret;
1323
1324 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001325 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001326 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001327 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001328 (unsigned long) ia64_rse_skip_regs(*state, 1),
1329 sizeof(long), (void *) valp);
1330 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001331}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332
1333static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001334set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001335{
Roland McGrath08267b82004-02-20 22:56:43 +00001336 int req = PTRACE_POKEDATA;
1337 void *ap;
1338
1339 if (ia32) {
1340 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1341 req = PTRACE_POKEUSER;
1342 } else
1343 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001344 errno = 0;
1345 ptrace(req, tcp->pid, ap, val);
1346 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001347}
1348
1349static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001350set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351{
Roland McGrath08267b82004-02-20 22:56:43 +00001352 int req = PTRACE_POKEDATA;
1353 void *ap;
1354
1355 if (ia32) {
1356 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1357 req = PTRACE_POKEUSER;
1358 } else
1359 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001360 errno = 0;
1361 ptrace(req, tcp->pid, ap, val);
1362 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001363}
1364
Roland McGrathb659f872008-07-18 01:19:36 +00001365/* ia64 does not return the input arguments from functions (and syscalls)
1366 according to ia64 RSE (Register Stack Engine) behavior. */
1367
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001368# define restore_arg0(tcp, state, val) ((void) (state), 0)
1369# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001370
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001371#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001372
Mike Frysinger8566c502009-10-12 11:05:14 -04001373typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001374
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001375# define arg_setup(tcp, state) \
1376 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1377# define arg_finish_change(tcp, state) \
1378 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001379
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001380# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1381# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1382# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1383# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1384# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001385
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001386#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001387
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001388# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001389/* Note: this is only true for the `clone' system call, which handles
1390 arguments specially. We could as well say that its first two arguments
1391 are swapped relative to other architectures, but that would just be
1392 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001393# define arg0_offset PT_GPR3
1394# define arg1_offset PT_ORIGGPR2
1395# define restore_arg0(tcp, state, val) ((void) (state), 0)
1396# define restore_arg1(tcp, state, val) ((void) (state), 0)
1397# define arg0_index 1
1398# define arg1_index 0
1399# elif defined(ALPHA) || defined(MIPS)
1400# define arg0_offset REG_A0
1401# define arg1_offset (REG_A0+1)
1402# elif defined(AVR32)
1403# define arg0_offset (REG_R12)
1404# define arg1_offset (REG_R11)
1405# elif defined(POWERPC)
1406# define arg0_offset (sizeof(unsigned long)*PT_R3)
1407# define arg1_offset (sizeof(unsigned long)*PT_R4)
1408# define restore_arg0(tcp, state, val) ((void) (state), 0)
1409# elif defined(HPPA)
1410# define arg0_offset PT_GR26
1411# define arg1_offset (PT_GR26-4)
1412# elif defined(X86_64)
1413# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1414# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1415# elif defined(SH)
1416# define arg0_offset (4*(REG_REG0+4))
1417# define arg1_offset (4*(REG_REG0+5))
1418# elif defined(SH64)
1419 /* ABI defines arg0 & 1 in r2 & r3 */
1420# define arg0_offset (REG_OFFSET+16)
1421# define arg1_offset (REG_OFFSET+24)
1422# define restore_arg0(tcp, state, val) 0
1423# elif defined CRISV10 || defined CRISV32
1424# define arg0_offset (4*PT_R11)
1425# define arg1_offset (4*PT_ORIG_R10)
1426# define restore_arg0(tcp, state, val) 0
1427# define restore_arg1(tcp, state, val) 0
1428# define arg0_index 1
1429# define arg1_index 0
1430# else
1431# define arg0_offset 0
1432# define arg1_offset 4
1433# if defined ARM
1434# define restore_arg0(tcp, state, val) 0
1435# endif
1436# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437
1438typedef int arg_setup_state;
1439
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001440# define arg_setup(tcp, state) (0)
1441# define arg_finish_change(tcp, state) 0
1442# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1443# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444
1445static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001446set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001447{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001448 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001449}
1450
1451static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001452set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001454 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455}
1456
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001457#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001458
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001459#ifndef restore_arg0
1460# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1461#endif
1462#ifndef restore_arg1
1463# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1464#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001465
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001466#ifndef arg0_index
1467# define arg0_index 0
1468# define arg1_index 1
1469#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001470
Roland McGrathd81f1d92003-01-09 06:53:34 +00001471int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001472setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001473{
Roland McGrath3291ef22008-05-20 00:34:34 +00001474 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001475 arg_setup_state state;
1476
1477 if (tcp->flags & TCB_BPTSET) {
1478 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1479 return -1;
1480 }
1481
Roland McGrath3291ef22008-05-20 00:34:34 +00001482 /*
1483 * It's a silly kludge to initialize this with a search at runtime.
1484 * But it's better than maintaining another magic thing in the
1485 * godforsaken tables.
1486 */
1487 if (clone_scno[current_personality] == 0) {
1488 int i;
1489 for (i = 0; i < nsyscalls; ++i)
1490 if (sysent[i].sys_func == sys_clone) {
1491 clone_scno[current_personality] = i;
1492 break;
1493 }
1494 }
1495
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001496 if (sysent[tcp->scno].sys_func == sys_fork ||
1497 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001498 if (arg_setup(tcp, &state) < 0
1499 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1500 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001501 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001502 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1503 || set_arg1(tcp, &state, 0) < 0
1504 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001505 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001506 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1507 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001508 tcp->flags |= TCB_BPTSET;
1509 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001510 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001511
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001512 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001513 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001514 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001515 vfork semantics into plain fork - each application must not
1516 depend on the vfork specifics according to POSIX. We would
1517 hang waiting for the parent resume otherwise. We need to
1518 clear also CLONE_VM but only in the CLONE_VFORK case as
1519 otherwise we would break pthread_create. */
1520
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001521 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1522 if (new_arg0 & CLONE_VFORK)
1523 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1524 if (arg_setup(tcp, &state) < 0
1525 || set_arg0(tcp, &state, new_arg0) < 0
1526 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001527 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001528 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001529 tcp->inst[0] = tcp->u_arg[arg0_index];
1530 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001531 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001532 }
1533
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001534 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1535 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001536 return -1;
1537}
1538
1539int
Denys Vlasenko12014262011-05-30 14:00:14 +02001540clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001541{
1542 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001543 if (arg_setup(tcp, &state) < 0
1544 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1545 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1546 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001547 if (errno != ESRCH)
1548 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001549 tcp->flags &= ~TCB_BPTSET;
1550 return 0;
1551}