blob: 18d29b74dc440bc32fb45cb6eaac24604e28f9f6 [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
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100973#if !defined(SPARC) && !defined(SPARC64)
974# define PTRACE_WRITETEXT 101
975# define PTRACE_WRITEDATA 102
976#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977
978int
Denys Vlasenko12014262011-05-30 14:00:14 +0200979upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980{
981 long val;
982
Roland McGratheb9e2e82009-06-02 16:49:22 -0700983 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100984 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700985 if (val == -1 && errno) {
986 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100987 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700988 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700990 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 *res = val;
992 return 0;
993}
994
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000996printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997{
Roland McGrath7a918832005-02-02 20:55:23 +0000998#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
999 sizeof(long) == 8 ? "[????????????????] " : \
1000 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001002#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 long eip;
1004
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001005 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001006 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 return;
1008 }
1009 tprintf("[%08lx] ", eip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001010#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001011 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001012 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001013 PRINTBADPC;
1014 return;
1015 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001016# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001017 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001018# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001019 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001020# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001021
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001022#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001023 long rip;
1024
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001025 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001026 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001027 return;
1028 }
1029 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001030#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001031 long ip;
1032
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001033 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001034 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001035 return;
1036 }
1037 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001038#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 long pc;
1040
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001041 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001042 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 return;
1044 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001045# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001046 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001047# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001049# endif
1050#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 long pc;
1052
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001053 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001054 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 return;
1056 }
1057 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001058#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 long pc;
1060
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001061 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001062 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063 return;
1064 }
1065 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001066#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001067 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001068 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001069 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 return;
1071 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001072# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001073 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001074# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001075 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001076# endif
1077#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001078 long pc;
1079
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001080 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001081 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001082 return;
1083 }
1084 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001085#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001086 long pc;
1087
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001088 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001089 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001090 return;
1091 }
1092 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001093#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001094 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001095
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001096 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001097 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001098 return;
1099 }
1100 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001101#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001102 long pc;
1103
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001104 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001105 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001106 return;
1107 }
1108 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001109#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001110 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001111
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001112 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001113 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001114 return;
1115 }
1116 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001117#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001118 long pc;
1119
1120 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001121 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001122 return;
1123 }
1124 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001125#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001126 long pc;
1127
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001128 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001129 PRINTBADPC;
1130 return;
1131 }
1132 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001133#elif defined(CRISV10)
1134 long pc;
1135
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001136 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001137 PRINTBADPC;
1138 return;
1139 }
1140 tprintf("[%08lx] ", pc);
1141#elif defined(CRISV32)
1142 long pc;
1143
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001144 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001145 PRINTBADPC;
1146 return;
1147 }
1148 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001149#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150}
1151
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001152/*
1153 * These #if's are huge, please indent them correctly.
1154 * It's easy to get confused otherwise.
1155 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001157#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001158
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001159#ifndef CLONE_PTRACE
1160# define CLONE_PTRACE 0x00002000
1161#endif
1162#ifndef CLONE_VFORK
1163# define CLONE_VFORK 0x00004000
1164#endif
1165#ifndef CLONE_VM
1166# define CLONE_VM 0x00000100
1167#endif
1168#ifndef CLONE_STOPPED
1169# define CLONE_STOPPED 0x02000000
1170#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001171
Denys Vlasenko081533c2012-03-17 02:17:51 +01001172static int
1173change_syscall(struct tcb *tcp, int new)
1174{
1175#if defined(I386)
1176 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1177 return -1;
1178 return 0;
1179#elif defined(X86_64)
1180 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1181 return -1;
1182 return 0;
1183#elif defined(POWERPC)
1184 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1185 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1186 return -1;
1187 return 0;
1188#elif defined(S390) || defined(S390X)
1189 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1190 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1191 return -1;
1192 return 0;
1193#elif defined(M68K)
1194 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1195 return -1;
1196 return 0;
1197#elif defined(SPARC) || defined(SPARC64)
1198 struct pt_regs regs;
1199 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1200 return -1;
1201 regs.u_regs[U_REG_G1] = new;
1202 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1203 return -1;
1204 return 0;
1205#elif defined(MIPS)
1206 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1207 return -1;
1208 return 0;
1209#elif defined(ALPHA)
1210 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1211 return -1;
1212 return 0;
1213#elif defined(AVR32)
1214 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1215 return -1;
1216 return 0;
1217#elif defined(BFIN)
1218 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1219 return -1;
1220 return 0;
1221#elif defined(IA64)
1222 if (ia32) {
1223 switch (new) {
1224 case 2:
1225 break; /* x86 SYS_fork */
1226 case SYS_clone:
1227 new = 120;
1228 break;
1229 default:
1230 fprintf(stderr, "%s: unexpected syscall %d\n",
1231 __FUNCTION__, new);
1232 return -1;
1233 }
1234 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1235 return -1;
1236 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1237 return -1;
1238 return 0;
1239#elif defined(HPPA)
1240 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1241 return -1;
1242 return 0;
1243#elif defined(SH)
1244 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1245 return -1;
1246 return 0;
1247#elif defined(SH64)
1248 /* Top half of reg encodes the no. of args n as 0x1n.
1249 Assume 0 args as kernel never actually checks... */
1250 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1251 0x100000 | new) < 0)
1252 return -1;
1253 return 0;
1254#elif defined(CRISV10) || defined(CRISV32)
1255 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1256 return -1;
1257 return 0;
1258#elif defined(ARM)
1259 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1260# ifndef PTRACE_SET_SYSCALL
1261# define PTRACE_SET_SYSCALL 23
1262# endif
1263 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1264 return -1;
1265 return 0;
1266#elif defined(TILE)
1267 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1268 (char*)PTREGS_OFFSET_REG(0),
1269 new) != 0)
1270 return -1;
1271 return 0;
1272#elif defined(MICROBLAZE)
1273 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1274 return -1;
1275 return 0;
1276#else
1277#warning Do not know how to handle change_syscall for this architecture
1278#endif /* architecture */
1279 return -1;
1280}
1281
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001282#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
1284typedef unsigned long *arg_setup_state;
1285
1286static int
1287arg_setup(struct tcb *tcp, arg_setup_state *state)
1288{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001289 unsigned long cfm, sof, sol;
1290 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291
Jan Kratochvil1f942712008-08-06 21:38:52 +00001292 if (ia32) {
1293 /* Satisfy a false GCC warning. */
1294 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001295 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001296 }
Roland McGrath08267b82004-02-20 22:56:43 +00001297
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001298 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001300 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301 return -1;
1302
1303 sof = (cfm >> 0) & 0x7f;
1304 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001305 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001306
Jan Kratochvil1f942712008-08-06 21:38:52 +00001307 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001308 return 0;
1309}
1310
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001311# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001312
Roland McGrathd81f1d92003-01-09 06:53:34 +00001313static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001314get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001315{
Roland McGrath08267b82004-02-20 22:56:43 +00001316 int ret;
1317
1318 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001319 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001320 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001321 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001322 (unsigned long) ia64_rse_skip_regs(*state, 0),
1323 sizeof(long), (void *) valp);
1324 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001325}
1326
1327static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001328get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001329{
Roland McGrath08267b82004-02-20 22:56:43 +00001330 int ret;
1331
1332 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001333 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001334 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001335 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001336 (unsigned long) ia64_rse_skip_regs(*state, 1),
1337 sizeof(long), (void *) valp);
1338 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340
1341static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001342set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001343{
Roland McGrath08267b82004-02-20 22:56:43 +00001344 int req = PTRACE_POKEDATA;
1345 void *ap;
1346
1347 if (ia32) {
1348 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1349 req = PTRACE_POKEUSER;
1350 } else
1351 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001352 errno = 0;
1353 ptrace(req, tcp->pid, ap, val);
1354 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355}
1356
1357static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001358set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001359{
Roland McGrath08267b82004-02-20 22:56:43 +00001360 int req = PTRACE_POKEDATA;
1361 void *ap;
1362
1363 if (ia32) {
1364 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1365 req = PTRACE_POKEUSER;
1366 } else
1367 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001368 errno = 0;
1369 ptrace(req, tcp->pid, ap, val);
1370 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371}
1372
Roland McGrathb659f872008-07-18 01:19:36 +00001373/* ia64 does not return the input arguments from functions (and syscalls)
1374 according to ia64 RSE (Register Stack Engine) behavior. */
1375
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001376# define restore_arg0(tcp, state, val) ((void) (state), 0)
1377# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001378
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001379#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380
Mike Frysinger8566c502009-10-12 11:05:14 -04001381typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001382
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001383# define arg_setup(tcp, state) \
1384 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1385# define arg_finish_change(tcp, state) \
1386 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001387
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001388# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1389# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1390# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1391# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1392# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001393
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001394#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001395
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001396# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001397/* Note: this is only true for the `clone' system call, which handles
1398 arguments specially. We could as well say that its first two arguments
1399 are swapped relative to other architectures, but that would just be
1400 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001401# define arg0_offset PT_GPR3
1402# define arg1_offset PT_ORIGGPR2
1403# define restore_arg0(tcp, state, val) ((void) (state), 0)
1404# define restore_arg1(tcp, state, val) ((void) (state), 0)
1405# define arg0_index 1
1406# define arg1_index 0
1407# elif defined(ALPHA) || defined(MIPS)
1408# define arg0_offset REG_A0
1409# define arg1_offset (REG_A0+1)
1410# elif defined(AVR32)
1411# define arg0_offset (REG_R12)
1412# define arg1_offset (REG_R11)
1413# elif defined(POWERPC)
1414# define arg0_offset (sizeof(unsigned long)*PT_R3)
1415# define arg1_offset (sizeof(unsigned long)*PT_R4)
1416# define restore_arg0(tcp, state, val) ((void) (state), 0)
1417# elif defined(HPPA)
1418# define arg0_offset PT_GR26
1419# define arg1_offset (PT_GR26-4)
1420# elif defined(X86_64)
1421# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1422# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1423# elif defined(SH)
1424# define arg0_offset (4*(REG_REG0+4))
1425# define arg1_offset (4*(REG_REG0+5))
1426# elif defined(SH64)
1427 /* ABI defines arg0 & 1 in r2 & r3 */
1428# define arg0_offset (REG_OFFSET+16)
1429# define arg1_offset (REG_OFFSET+24)
1430# define restore_arg0(tcp, state, val) 0
1431# elif defined CRISV10 || defined CRISV32
1432# define arg0_offset (4*PT_R11)
1433# define arg1_offset (4*PT_ORIG_R10)
1434# define restore_arg0(tcp, state, val) 0
1435# define restore_arg1(tcp, state, val) 0
1436# define arg0_index 1
1437# define arg1_index 0
1438# else
1439# define arg0_offset 0
1440# define arg1_offset 4
1441# if defined ARM
1442# define restore_arg0(tcp, state, val) 0
1443# endif
1444# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001445
1446typedef int arg_setup_state;
1447
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001448# define arg_setup(tcp, state) (0)
1449# define arg_finish_change(tcp, state) 0
1450# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1451# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001452
1453static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001454set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001456 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001457}
1458
1459static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001460set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001461{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001462 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001463}
1464
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001465#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001466
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001467#ifndef restore_arg0
1468# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1469#endif
1470#ifndef restore_arg1
1471# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1472#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001473
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001474#ifndef arg0_index
1475# define arg0_index 0
1476# define arg1_index 1
1477#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001478
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001480setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481{
Roland McGrath3291ef22008-05-20 00:34:34 +00001482 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483 arg_setup_state state;
1484
1485 if (tcp->flags & TCB_BPTSET) {
1486 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1487 return -1;
1488 }
1489
Roland McGrath3291ef22008-05-20 00:34:34 +00001490 /*
1491 * It's a silly kludge to initialize this with a search at runtime.
1492 * But it's better than maintaining another magic thing in the
1493 * godforsaken tables.
1494 */
1495 if (clone_scno[current_personality] == 0) {
1496 int i;
1497 for (i = 0; i < nsyscalls; ++i)
1498 if (sysent[i].sys_func == sys_clone) {
1499 clone_scno[current_personality] = i;
1500 break;
1501 }
1502 }
1503
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001504 if (sysent[tcp->scno].sys_func == sys_fork ||
1505 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001506 if (arg_setup(tcp, &state) < 0
1507 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1508 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001509 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001510 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1511 || set_arg1(tcp, &state, 0) < 0
1512 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001513 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001514 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1515 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001516 tcp->flags |= TCB_BPTSET;
1517 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001518 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001519
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001520 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001521 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001522 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001523 vfork semantics into plain fork - each application must not
1524 depend on the vfork specifics according to POSIX. We would
1525 hang waiting for the parent resume otherwise. We need to
1526 clear also CLONE_VM but only in the CLONE_VFORK case as
1527 otherwise we would break pthread_create. */
1528
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001529 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1530 if (new_arg0 & CLONE_VFORK)
1531 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1532 if (arg_setup(tcp, &state) < 0
1533 || set_arg0(tcp, &state, new_arg0) < 0
1534 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001535 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001536 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001537 tcp->inst[0] = tcp->u_arg[arg0_index];
1538 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001539 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001540 }
1541
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001542 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1543 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001544 return -1;
1545}
1546
1547int
Denys Vlasenko12014262011-05-30 14:00:14 +02001548clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001549{
1550 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001551 if (arg_setup(tcp, &state) < 0
1552 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1553 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1554 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001555 if (errno != ESRCH)
1556 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001557 tcp->flags &= ~TCB_BPTSET;
1558 return 0;
1559}