blob: 9173b48f128c5c2a8e4252b1435095d0447b58e8 [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);
Roland McGratheac26fc2005-02-02 02:48:53 +00001010
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001011#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001012 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001013 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001014 PRINTBADPC;
1015 return;
1016 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001017# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001018 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001019# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001020 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001021# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001022
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001023#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001024 long rip;
1025
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001026 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001027 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001028 return;
1029 }
1030 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001031#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001032 long ip;
1033
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001034 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001035 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001036 return;
1037 }
1038 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001039#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 long pc;
1041
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001042 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001043 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044 return;
1045 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001046# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001047 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001048# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001050# endif
1051#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 long pc;
1053
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001054 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001055 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 return;
1057 }
1058 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001059#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 long pc;
1061
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001062 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001063 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 return;
1065 }
1066 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001067#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001068 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001069 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001070 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 return;
1072 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001073# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001074 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001075# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001076 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001077# endif
1078#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001079 long pc;
1080
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001081 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001082 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001083 return;
1084 }
1085 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001086#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001087 long pc;
1088
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001089 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001090 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001091 return;
1092 }
1093 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001094#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001095 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001096
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001097 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001098 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001099 return;
1100 }
1101 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001102#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001103 long pc;
1104
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001105 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001106 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001107 return;
1108 }
1109 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001110#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001111 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001112
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001113 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001114 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001115 return;
1116 }
1117 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001118#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001119 long pc;
1120
1121 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001122 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001123 return;
1124 }
1125 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001126#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001127 long pc;
1128
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001129 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001130 PRINTBADPC;
1131 return;
1132 }
1133 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001134#elif defined(CRISV10)
1135 long pc;
1136
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001137 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001138 PRINTBADPC;
1139 return;
1140 }
1141 tprintf("[%08lx] ", pc);
1142#elif defined(CRISV32)
1143 long pc;
1144
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001145 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146 PRINTBADPC;
1147 return;
1148 }
1149 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001150#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151}
1152
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001153/*
1154 * These #if's are huge, please indent them correctly.
1155 * It's easy to get confused otherwise.
1156 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001158#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001159
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001160#ifndef CLONE_PTRACE
1161# define CLONE_PTRACE 0x00002000
1162#endif
1163#ifndef CLONE_VFORK
1164# define CLONE_VFORK 0x00004000
1165#endif
1166#ifndef CLONE_VM
1167# define CLONE_VM 0x00000100
1168#endif
1169#ifndef CLONE_STOPPED
1170# define CLONE_STOPPED 0x02000000
1171#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001173#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001174
1175typedef unsigned long *arg_setup_state;
1176
1177static int
1178arg_setup(struct tcb *tcp, arg_setup_state *state)
1179{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001180 unsigned long cfm, sof, sol;
1181 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182
Jan Kratochvil1f942712008-08-06 21:38:52 +00001183 if (ia32) {
1184 /* Satisfy a false GCC warning. */
1185 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001186 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001187 }
Roland McGrath08267b82004-02-20 22:56:43 +00001188
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001189 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001190 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001191 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001192 return -1;
1193
1194 sof = (cfm >> 0) & 0x7f;
1195 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001196 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001197
Jan Kratochvil1f942712008-08-06 21:38:52 +00001198 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001199 return 0;
1200}
1201
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001202# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001203
Roland McGrathd81f1d92003-01-09 06:53:34 +00001204static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001205get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206{
Roland McGrath08267b82004-02-20 22:56:43 +00001207 int ret;
1208
1209 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001210 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001211 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001212 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001213 (unsigned long) ia64_rse_skip_regs(*state, 0),
1214 sizeof(long), (void *) valp);
1215 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001216}
1217
1218static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001219get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220{
Roland McGrath08267b82004-02-20 22:56:43 +00001221 int ret;
1222
1223 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001224 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001225 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001226 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001227 (unsigned long) ia64_rse_skip_regs(*state, 1),
1228 sizeof(long), (void *) valp);
1229 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001230}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001231
1232static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001233set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001234{
Roland McGrath08267b82004-02-20 22:56:43 +00001235 int req = PTRACE_POKEDATA;
1236 void *ap;
1237
1238 if (ia32) {
1239 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1240 req = PTRACE_POKEUSER;
1241 } else
1242 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001243 errno = 0;
1244 ptrace(req, tcp->pid, ap, val);
1245 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001246}
1247
1248static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001249set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001250{
Roland McGrath08267b82004-02-20 22:56:43 +00001251 int req = PTRACE_POKEDATA;
1252 void *ap;
1253
1254 if (ia32) {
1255 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1256 req = PTRACE_POKEUSER;
1257 } else
1258 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001259 errno = 0;
1260 ptrace(req, tcp->pid, ap, val);
1261 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262}
1263
Roland McGrathb659f872008-07-18 01:19:36 +00001264/* ia64 does not return the input arguments from functions (and syscalls)
1265 according to ia64 RSE (Register Stack Engine) behavior. */
1266
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001267# define restore_arg0(tcp, state, val) ((void) (state), 0)
1268# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001269
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001270#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271
Mike Frysinger8566c502009-10-12 11:05:14 -04001272typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001274# define arg_setup(tcp, state) \
1275 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1276# define arg_finish_change(tcp, state) \
1277 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001278
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001279# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1280# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1281# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1282# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1283# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001285#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001287# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001288/* Note: this is only true for the `clone' system call, which handles
1289 arguments specially. We could as well say that its first two arguments
1290 are swapped relative to other architectures, but that would just be
1291 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001292# define arg0_offset PT_GPR3
1293# define arg1_offset PT_ORIGGPR2
1294# define restore_arg0(tcp, state, val) ((void) (state), 0)
1295# define restore_arg1(tcp, state, val) ((void) (state), 0)
1296# define arg0_index 1
1297# define arg1_index 0
1298# elif defined(ALPHA) || defined(MIPS)
1299# define arg0_offset REG_A0
1300# define arg1_offset (REG_A0+1)
1301# elif defined(AVR32)
1302# define arg0_offset (REG_R12)
1303# define arg1_offset (REG_R11)
1304# elif defined(POWERPC)
1305# define arg0_offset (sizeof(unsigned long)*PT_R3)
1306# define arg1_offset (sizeof(unsigned long)*PT_R4)
1307# define restore_arg0(tcp, state, val) ((void) (state), 0)
1308# elif defined(HPPA)
1309# define arg0_offset PT_GR26
1310# define arg1_offset (PT_GR26-4)
1311# elif defined(X86_64)
1312# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1313# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1314# elif defined(SH)
1315# define arg0_offset (4*(REG_REG0+4))
1316# define arg1_offset (4*(REG_REG0+5))
1317# elif defined(SH64)
1318 /* ABI defines arg0 & 1 in r2 & r3 */
1319# define arg0_offset (REG_OFFSET+16)
1320# define arg1_offset (REG_OFFSET+24)
1321# define restore_arg0(tcp, state, val) 0
1322# elif defined CRISV10 || defined CRISV32
1323# define arg0_offset (4*PT_R11)
1324# define arg1_offset (4*PT_ORIG_R10)
1325# define restore_arg0(tcp, state, val) 0
1326# define restore_arg1(tcp, state, val) 0
1327# define arg0_index 1
1328# define arg1_index 0
1329# else
1330# define arg0_offset 0
1331# define arg1_offset 4
1332# if defined ARM
1333# define restore_arg0(tcp, state, val) 0
1334# endif
1335# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336
1337typedef int arg_setup_state;
1338
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001339# define arg_setup(tcp, state) (0)
1340# define arg_finish_change(tcp, state) 0
1341# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1342# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001343
1344static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001345set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001346{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001347 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348}
1349
1350static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001351set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001353 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001354}
1355
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001356#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001358#ifndef restore_arg0
1359# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1360#endif
1361#ifndef restore_arg1
1362# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1363#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001364
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001365#ifndef arg0_index
1366# define arg0_index 0
1367# define arg1_index 1
1368#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001369
Roland McGrathd81f1d92003-01-09 06:53:34 +00001370int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001371setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001372{
Roland McGrath3291ef22008-05-20 00:34:34 +00001373 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001374 arg_setup_state state;
1375
1376 if (tcp->flags & TCB_BPTSET) {
1377 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1378 return -1;
1379 }
1380
Roland McGrath3291ef22008-05-20 00:34:34 +00001381 /*
1382 * It's a silly kludge to initialize this with a search at runtime.
1383 * But it's better than maintaining another magic thing in the
1384 * godforsaken tables.
1385 */
1386 if (clone_scno[current_personality] == 0) {
1387 int i;
1388 for (i = 0; i < nsyscalls; ++i)
1389 if (sysent[i].sys_func == sys_clone) {
1390 clone_scno[current_personality] = i;
1391 break;
1392 }
1393 }
1394
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001395 if (sysent[tcp->scno].sys_func == sys_fork ||
1396 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001397 if (arg_setup(tcp, &state) < 0
1398 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1399 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001400 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001401 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1402 || set_arg1(tcp, &state, 0) < 0
1403 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001404 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001405 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1406 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407 tcp->flags |= TCB_BPTSET;
1408 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001409 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001410
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001411 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001412 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001413 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001414 vfork semantics into plain fork - each application must not
1415 depend on the vfork specifics according to POSIX. We would
1416 hang waiting for the parent resume otherwise. We need to
1417 clear also CLONE_VM but only in the CLONE_VFORK case as
1418 otherwise we would break pthread_create. */
1419
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001420 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1421 if (new_arg0 & CLONE_VFORK)
1422 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1423 if (arg_setup(tcp, &state) < 0
1424 || set_arg0(tcp, &state, new_arg0) < 0
1425 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001426 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001428 tcp->inst[0] = tcp->u_arg[arg0_index];
1429 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001430 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001431 }
1432
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001433 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1434 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001435 return -1;
1436}
1437
1438int
Denys Vlasenko12014262011-05-30 14:00:14 +02001439clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001440{
1441 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001442 if (arg_setup(tcp, &state) < 0
1443 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1444 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1445 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001446 if (errno != ESRCH)
1447 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001448 tcp->flags &= ~TCB_BPTSET;
1449 return 0;
1450}