blob: 9a7770517b650f048a1d60931651530a99f2e1e4 [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 \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100634 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000635#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100636 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000637#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100638 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000639#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000640 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000641#define sizeof_iov sizeof(*iov)
642#define iov_iov_base(i) iov[i].iov_base
643#define iov_iov_len(i) iov[i].iov_len
644#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000645 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200646 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000647
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200648 size = sizeof_iov * len;
649 /* Assuming no sane program has millions of iovs */
650 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000651 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200652 fprintf(stderr, "Out of memory\n");
653 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000654 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000655 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000656 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000657 /* include the buffer number to make it easy to
658 * match up the trace with the source */
659 tprintf(" * %lu bytes in buffer %d\n",
660 (unsigned long)iov_iov_len(i), i);
661 dumpstr(tcp, (long) iov_iov_base(i),
662 iov_iov_len(i));
663 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000664 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200665 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000666#undef sizeof_iov
667#undef iov_iov_base
668#undef iov_iov_len
669#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000670}
671#endif
672
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673void
Denys Vlasenko12014262011-05-30 14:00:14 +0200674dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675{
676 static int strsize = -1;
677 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678 char *s;
679 int i, j;
680
681 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200682 free(str);
683 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200684 if (!str) {
685 strsize = -1;
686 fprintf(stderr, "Out of memory\n");
687 return;
688 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689 strsize = len;
690 }
691
692 if (umoven(tcp, addr, len, (char *) str) < 0)
693 return;
694
695 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200696 char outstr[80];
697
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698 s = outstr;
699 sprintf(s, " | %05x ", i);
700 s += 9;
701 for (j = 0; j < 16; j++) {
702 if (j == 8)
703 *s++ = ' ';
704 if (i + j < len) {
705 sprintf(s, " %02x", str[i + j]);
706 s += 3;
707 }
708 else {
709 *s++ = ' '; *s++ = ' '; *s++ = ' ';
710 }
711 }
712 *s++ = ' '; *s++ = ' ';
713 for (j = 0; j < 16; j++) {
714 if (j == 8)
715 *s++ = ' ';
716 if (i + j < len) {
717 if (isprint(str[i + j]))
718 *s++ = str[i + j];
719 else
720 *s++ = '.';
721 }
722 else
723 *s++ = ' ';
724 }
725 tprintf("%s |\n", outstr);
726 }
727}
728
Mike Frysinger612659e2012-02-14 14:38:28 +0100729#ifdef HAVE_PROCESS_VM_READV
730/* C library supports this, but the kernel might not. */
731static bool process_vm_readv_not_supported = 0;
732#else
733
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100734/* Need to do this since process_vm_readv() is not yet available in libc.
735 * When libc is be updated, only "static bool process_vm_readv_not_supported"
736 * line should remain.
737 */
738#if !defined(__NR_process_vm_readv)
739# if defined(I386)
740# define __NR_process_vm_readv 347
741# elif defined(X86_64)
742# define __NR_process_vm_readv 310
743# elif defined(POWERPC)
744# define __NR_process_vm_readv 351
745# endif
746#endif
747
748#if defined(__NR_process_vm_readv)
749static bool process_vm_readv_not_supported = 0;
750static ssize_t process_vm_readv(pid_t pid,
751 const struct iovec *lvec,
752 unsigned long liovcnt,
753 const struct iovec *rvec,
754 unsigned long riovcnt,
755 unsigned long flags)
756{
757 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
758}
759#else
760static bool process_vm_readv_not_supported = 1;
761# define process_vm_readv(...) (errno = ENOSYS, -1)
762#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100763
764#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100765
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000766#define PAGMASK (~(PAGSIZ - 1))
767/*
768 * move `len' bytes of data from process `pid'
769 * at address `addr' to our space at `laddr'
770 */
771int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000772umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700774 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000775 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100776 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 union {
778 long val;
779 char x[sizeof(long)];
780 } u;
781
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100782#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100783 if (current_wordsize < sizeof(addr))
784 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100785#endif
786
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100787 if (!process_vm_readv_not_supported) {
788 struct iovec local[1], remote[1];
789 int r;
790
791 local[0].iov_base = laddr;
792 remote[0].iov_base = (void*)addr;
793 local[0].iov_len = remote[0].iov_len = len;
794 r = process_vm_readv(pid,
795 local, 1,
796 remote, 1,
797 /*flags:*/ 0
798 );
799 if (r < 0) {
800 if (errno == ENOSYS)
801 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100802 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
803 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100804 perror("process_vm_readv");
805 goto vm_readv_didnt_work;
806 }
807 return r;
808 }
809 vm_readv_didnt_work:
810
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100811 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 if (addr & (sizeof(long) - 1)) {
813 /* addr not a multiple of sizeof(long) */
814 n = addr - (addr & -sizeof(long)); /* residue */
815 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700816 errno = 0;
817 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
818 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700819 /* But if not started, we had a bogus address. */
820 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100821 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700822 return -1;
823 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000824 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100825 m = MIN(sizeof(long) - n, len);
826 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000827 addr += sizeof(long), laddr += m, len -= m;
828 }
829 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700830 errno = 0;
831 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
832 if (errno) {
833 if (started && (errno==EPERM || errno==EIO)) {
834 /* Ran into 'end of memory' - stupid "printpath" */
835 return 0;
836 }
837 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100838 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700839 return -1;
840 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000841 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100842 m = MIN(sizeof(long), len);
843 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000844 addr += sizeof(long), laddr += m, len -= m;
845 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 return 0;
848}
849
850/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100851 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100853 *
854 * Returns < 0 on error, > 0 if NUL was seen,
855 * (TODO if useful: return count of bytes including NUL),
856 * else 0 if len bytes were read but no NUL byte seen.
857 *
858 * Note: there is no guarantee we won't overwrite some bytes
859 * in laddr[] _after_ terminating NUL (but, of course,
860 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000861 */
862int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000863umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100865 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700866 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867 int i, n, m;
868 union {
869 long val;
870 char x[sizeof(long)];
871 } u;
872
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000873#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100874 if (current_wordsize < sizeof(addr))
875 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000876#endif
877
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100878 if (!process_vm_readv_not_supported) {
879 struct iovec local[1], remote[1];
880
881 local[0].iov_base = laddr;
882 remote[0].iov_base = (void*)addr;
883
884 while (len > 0) {
885 int end_in_page;
886 int r;
887 int chunk_len;
888
889 /* Don't read kilobytes: most strings are short */
890 chunk_len = len;
891 if (chunk_len > 256)
892 chunk_len = 256;
893 /* Don't cross pages. I guess otherwise we can get EFAULT
894 * and fail to notice that terminating NUL lies
895 * in the existing (first) page.
896 * (I hope there aren't arches with pages < 4K)
897 */
898 end_in_page = ((addr + chunk_len) & 4095);
899 r = chunk_len - end_in_page;
900 if (r > 0) /* if chunk_len > end_in_page */
901 chunk_len = r; /* chunk_len -= end_in_page */
902
903 local[0].iov_len = remote[0].iov_len = chunk_len;
904 r = process_vm_readv(pid,
905 local, 1,
906 remote, 1,
907 /*flags:*/ 0
908 );
909 if (r < 0) {
910 if (errno == ENOSYS)
911 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100912 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
913 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100914 perror("process_vm_readv");
915 goto vm_readv_didnt_work;
916 }
917 if (memchr(local[0].iov_base, '\0', r))
918 return 1;
919 local[0].iov_base += r;
920 remote[0].iov_base += r;
921 len -= r;
922 }
923 return 0;
924 }
925 vm_readv_didnt_work:
926
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100927 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 if (addr & (sizeof(long) - 1)) {
929 /* addr not a multiple of sizeof(long) */
930 n = addr - (addr & -sizeof(long)); /* residue */
931 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700932 errno = 0;
933 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
934 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700935 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100936 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700937 return -1;
938 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000939 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100940 m = MIN(sizeof(long) - n, len);
941 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 while (n & (sizeof(long) - 1))
943 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100944 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 addr += sizeof(long), laddr += m, len -= m;
946 }
947 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700948 errno = 0;
949 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
950 if (errno) {
951 if (started && (errno==EPERM || errno==EIO)) {
952 /* Ran into 'end of memory' - stupid "printpath" */
953 return 0;
954 }
955 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100956 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700957 return -1;
958 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000959 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100960 m = MIN(sizeof(long), len);
961 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962 for (i = 0; i < sizeof(long); i++)
963 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100964 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 addr += sizeof(long), laddr += m, len -= m;
966 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000967 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968}
969
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970int
Denys Vlasenko12014262011-05-30 14:00:14 +0200971upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972{
973 long val;
974
Roland McGratheb9e2e82009-06-02 16:49:22 -0700975 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100976 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700977 if (val == -1 && errno) {
978 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100979 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700980 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700982 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 *res = val;
984 return 0;
985}
986
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000988printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989{
Roland McGrath7a918832005-02-02 20:55:23 +0000990#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
991 sizeof(long) == 8 ? "[????????????????] " : \
992 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100994#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 long eip;
996
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000997 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +0000998 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 return;
1000 }
1001 tprintf("[%08lx] ", eip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001002#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001003 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001004 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001005 PRINTBADPC;
1006 return;
1007 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001008# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001009 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001010# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001011 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001012# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001013
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001014#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001015 long rip;
1016
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001017 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001018 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001019 return;
1020 }
1021 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001022#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001023 long ip;
1024
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001025 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001026 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001027 return;
1028 }
1029 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001030#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 long pc;
1032
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001033 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001034 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 return;
1036 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001037# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001038 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001039# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001041# endif
1042#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 long pc;
1044
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001045 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001046 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 return;
1048 }
1049 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001050#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 long pc;
1052
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001053 if (upeek(tcp, REG_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(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001059 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001060 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001061 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 return;
1063 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001064# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001065 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001066# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001067 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001068# endif
1069#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001070 long pc;
1071
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001072 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001073 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001074 return;
1075 }
1076 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001077#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001078 long pc;
1079
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001080 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001081 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001082 return;
1083 }
1084 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001085#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001086 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001087
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001088 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001089 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001090 return;
1091 }
1092 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001093#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001094 long pc;
1095
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001096 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001097 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001098 return;
1099 }
1100 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001101#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001102 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001103
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001104 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001105 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001106 return;
1107 }
1108 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001109#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001110 long pc;
1111
1112 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001113 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001114 return;
1115 }
1116 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001117#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001118 long pc;
1119
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001120 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001121 PRINTBADPC;
1122 return;
1123 }
1124 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001125#elif defined(CRISV10)
1126 long pc;
1127
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001128 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001129 PRINTBADPC;
1130 return;
1131 }
1132 tprintf("[%08lx] ", pc);
1133#elif defined(CRISV32)
1134 long pc;
1135
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001136 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001137 PRINTBADPC;
1138 return;
1139 }
1140 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001141#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142}
1143
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001144/*
1145 * These #if's are huge, please indent them correctly.
1146 * It's easy to get confused otherwise.
1147 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001149#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001150
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001151#ifndef CLONE_PTRACE
1152# define CLONE_PTRACE 0x00002000
1153#endif
1154#ifndef CLONE_VFORK
1155# define CLONE_VFORK 0x00004000
1156#endif
1157#ifndef CLONE_VM
1158# define CLONE_VM 0x00000100
1159#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001160
Denys Vlasenko081533c2012-03-17 02:17:51 +01001161static int
1162change_syscall(struct tcb *tcp, int new)
1163{
1164#if defined(I386)
1165 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1166 return -1;
1167 return 0;
1168#elif defined(X86_64)
1169 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1170 return -1;
1171 return 0;
1172#elif defined(POWERPC)
1173 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1174 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1175 return -1;
1176 return 0;
1177#elif defined(S390) || defined(S390X)
1178 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1179 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1180 return -1;
1181 return 0;
1182#elif defined(M68K)
1183 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1184 return -1;
1185 return 0;
1186#elif defined(SPARC) || defined(SPARC64)
1187 struct pt_regs regs;
1188 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1189 return -1;
1190 regs.u_regs[U_REG_G1] = new;
1191 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1192 return -1;
1193 return 0;
1194#elif defined(MIPS)
1195 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1196 return -1;
1197 return 0;
1198#elif defined(ALPHA)
1199 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1200 return -1;
1201 return 0;
1202#elif defined(AVR32)
1203 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1204 return -1;
1205 return 0;
1206#elif defined(BFIN)
1207 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1208 return -1;
1209 return 0;
1210#elif defined(IA64)
1211 if (ia32) {
1212 switch (new) {
1213 case 2:
1214 break; /* x86 SYS_fork */
1215 case SYS_clone:
1216 new = 120;
1217 break;
1218 default:
1219 fprintf(stderr, "%s: unexpected syscall %d\n",
1220 __FUNCTION__, new);
1221 return -1;
1222 }
1223 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1224 return -1;
1225 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1226 return -1;
1227 return 0;
1228#elif defined(HPPA)
1229 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1230 return -1;
1231 return 0;
1232#elif defined(SH)
1233 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1234 return -1;
1235 return 0;
1236#elif defined(SH64)
1237 /* Top half of reg encodes the no. of args n as 0x1n.
1238 Assume 0 args as kernel never actually checks... */
1239 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1240 0x100000 | new) < 0)
1241 return -1;
1242 return 0;
1243#elif defined(CRISV10) || defined(CRISV32)
1244 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1245 return -1;
1246 return 0;
1247#elif defined(ARM)
1248 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1249# ifndef PTRACE_SET_SYSCALL
1250# define PTRACE_SET_SYSCALL 23
1251# endif
1252 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1253 return -1;
1254 return 0;
1255#elif defined(TILE)
1256 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1257 (char*)PTREGS_OFFSET_REG(0),
1258 new) != 0)
1259 return -1;
1260 return 0;
1261#elif defined(MICROBLAZE)
1262 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1263 return -1;
1264 return 0;
1265#else
1266#warning Do not know how to handle change_syscall for this architecture
1267#endif /* architecture */
1268 return -1;
1269}
1270
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001271#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272
1273typedef unsigned long *arg_setup_state;
1274
1275static int
1276arg_setup(struct tcb *tcp, arg_setup_state *state)
1277{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001278 unsigned long cfm, sof, sol;
1279 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001280
Jan Kratochvil1f942712008-08-06 21:38:52 +00001281 if (ia32) {
1282 /* Satisfy a false GCC warning. */
1283 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001284 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001285 }
Roland McGrath08267b82004-02-20 22:56:43 +00001286
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001287 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001288 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001289 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290 return -1;
1291
1292 sof = (cfm >> 0) & 0x7f;
1293 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001294 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295
Jan Kratochvil1f942712008-08-06 21:38:52 +00001296 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001297 return 0;
1298}
1299
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001300# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301
Roland McGrathd81f1d92003-01-09 06:53:34 +00001302static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001303get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304{
Roland McGrath08267b82004-02-20 22:56:43 +00001305 int ret;
1306
1307 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001308 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001309 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001310 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001311 (unsigned long) ia64_rse_skip_regs(*state, 0),
1312 sizeof(long), (void *) valp);
1313 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001314}
1315
1316static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001317get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318{
Roland McGrath08267b82004-02-20 22:56:43 +00001319 int ret;
1320
1321 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001322 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001323 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001324 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001325 (unsigned long) ia64_rse_skip_regs(*state, 1),
1326 sizeof(long), (void *) valp);
1327 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001328}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001329
1330static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001331set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332{
Roland McGrath08267b82004-02-20 22:56:43 +00001333 int req = PTRACE_POKEDATA;
1334 void *ap;
1335
1336 if (ia32) {
1337 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1338 req = PTRACE_POKEUSER;
1339 } else
1340 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001341 errno = 0;
1342 ptrace(req, tcp->pid, ap, val);
1343 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001344}
1345
1346static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001347set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348{
Roland McGrath08267b82004-02-20 22:56:43 +00001349 int req = PTRACE_POKEDATA;
1350 void *ap;
1351
1352 if (ia32) {
1353 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1354 req = PTRACE_POKEUSER;
1355 } else
1356 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001357 errno = 0;
1358 ptrace(req, tcp->pid, ap, val);
1359 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360}
1361
Roland McGrathb659f872008-07-18 01:19:36 +00001362/* ia64 does not return the input arguments from functions (and syscalls)
1363 according to ia64 RSE (Register Stack Engine) behavior. */
1364
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001365# define restore_arg0(tcp, state, val) ((void) (state), 0)
1366# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001367
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001368#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001369
Mike Frysinger8566c502009-10-12 11:05:14 -04001370typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001372# define arg_setup(tcp, state) \
1373 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1374# define arg_finish_change(tcp, state) \
1375 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001376
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001377# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1378# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1379# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1380# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1381# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001382
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001383#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001384
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001385# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001386/* Note: this is only true for the `clone' system call, which handles
1387 arguments specially. We could as well say that its first two arguments
1388 are swapped relative to other architectures, but that would just be
1389 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001390# define arg0_offset PT_GPR3
1391# define arg1_offset PT_ORIGGPR2
1392# define restore_arg0(tcp, state, val) ((void) (state), 0)
1393# define restore_arg1(tcp, state, val) ((void) (state), 0)
1394# define arg0_index 1
1395# define arg1_index 0
1396# elif defined(ALPHA) || defined(MIPS)
1397# define arg0_offset REG_A0
1398# define arg1_offset (REG_A0+1)
1399# elif defined(AVR32)
1400# define arg0_offset (REG_R12)
1401# define arg1_offset (REG_R11)
1402# elif defined(POWERPC)
1403# define arg0_offset (sizeof(unsigned long)*PT_R3)
1404# define arg1_offset (sizeof(unsigned long)*PT_R4)
1405# define restore_arg0(tcp, state, val) ((void) (state), 0)
1406# elif defined(HPPA)
1407# define arg0_offset PT_GR26
1408# define arg1_offset (PT_GR26-4)
1409# elif defined(X86_64)
1410# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1411# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1412# elif defined(SH)
1413# define arg0_offset (4*(REG_REG0+4))
1414# define arg1_offset (4*(REG_REG0+5))
1415# elif defined(SH64)
1416 /* ABI defines arg0 & 1 in r2 & r3 */
1417# define arg0_offset (REG_OFFSET+16)
1418# define arg1_offset (REG_OFFSET+24)
1419# define restore_arg0(tcp, state, val) 0
1420# elif defined CRISV10 || defined CRISV32
1421# define arg0_offset (4*PT_R11)
1422# define arg1_offset (4*PT_ORIG_R10)
1423# define restore_arg0(tcp, state, val) 0
1424# define restore_arg1(tcp, state, val) 0
1425# define arg0_index 1
1426# define arg1_index 0
1427# else
1428# define arg0_offset 0
1429# define arg1_offset 4
1430# if defined ARM
1431# define restore_arg0(tcp, state, val) 0
1432# endif
1433# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001434
1435typedef int arg_setup_state;
1436
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001437# define arg_setup(tcp, state) (0)
1438# define arg_finish_change(tcp, state) 0
1439# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1440# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001441
1442static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001443set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001446}
1447
1448static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001449set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001450{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001451 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001452}
1453
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001454#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001456#ifndef restore_arg0
1457# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1458#endif
1459#ifndef restore_arg1
1460# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1461#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001463#ifndef arg0_index
1464# define arg0_index 0
1465# define arg1_index 1
1466#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001467
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001469setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001470{
Roland McGrath3291ef22008-05-20 00:34:34 +00001471 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001472 arg_setup_state state;
1473
1474 if (tcp->flags & TCB_BPTSET) {
1475 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1476 return -1;
1477 }
1478
Roland McGrath3291ef22008-05-20 00:34:34 +00001479 /*
1480 * It's a silly kludge to initialize this with a search at runtime.
1481 * But it's better than maintaining another magic thing in the
1482 * godforsaken tables.
1483 */
1484 if (clone_scno[current_personality] == 0) {
1485 int i;
1486 for (i = 0; i < nsyscalls; ++i)
1487 if (sysent[i].sys_func == sys_clone) {
1488 clone_scno[current_personality] = i;
1489 break;
1490 }
1491 }
1492
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001493 if (sysent[tcp->scno].sys_func == sys_fork ||
1494 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001495 if (arg_setup(tcp, &state) < 0
1496 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1497 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001498 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001499 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1500 || set_arg1(tcp, &state, 0) < 0
1501 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001502 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001503 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1504 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001505 tcp->flags |= TCB_BPTSET;
1506 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001507 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001508
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001509 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001510 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001511 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001512 vfork semantics into plain fork - each application must not
1513 depend on the vfork specifics according to POSIX. We would
1514 hang waiting for the parent resume otherwise. We need to
1515 clear also CLONE_VM but only in the CLONE_VFORK case as
1516 otherwise we would break pthread_create. */
1517
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001518 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1519 if (new_arg0 & CLONE_VFORK)
1520 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1521 if (arg_setup(tcp, &state) < 0
1522 || set_arg0(tcp, &state, new_arg0) < 0
1523 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001524 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001525 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001526 tcp->inst[0] = tcp->u_arg[arg0_index];
1527 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001528 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001529 }
1530
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001531 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1532 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001533 return -1;
1534}
1535
1536int
Denys Vlasenko12014262011-05-30 14:00:14 +02001537clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001538{
1539 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001540 if (arg_setup(tcp, &state) < 0
1541 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1542 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1543 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001544 if (errno != ESRCH)
1545 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001546 tcp->flags &= ~TCB_BPTSET;
1547 return 0;
1548}