blob: 59665b7074219b17a0dfa24e1fe04ed0f889dee7 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010044# include <sys/uio.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000045#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000046
Denys Vlasenko84703742012-02-25 02:38:52 +010047#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000049#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000050
Denys Vlasenko84703742012-02-25 02:38:52 +010051#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000052# include <asm/ptrace_offsets.h>
53# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000054#endif
55
Wichert Akkerman36915a11999-07-13 15:45:02 +000056#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010057# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000058# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000059#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010060# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000061# ifdef HAVE_STRUCT_IA64_FPREG
62# define ia64_fpreg XXX_ia64_fpreg
63# endif
64# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
65# define pt_all_user_regs XXX_pt_all_user_regs
66# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010067# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000068# undef ia64_fpreg
69# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000070#endif
71
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010072#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000073# undef PTRACE_GETREGS
74# define PTRACE_GETREGS PTRACE_GETREGS64
75# undef PTRACE_SETREGS
76# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#endif
78
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079/* macros */
80#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010081# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
83#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010084# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085#endif
86
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087int
Denys Vlasenko12014262011-05-30 14:00:14 +020088tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089{
90 return a->tv_sec || a->tv_usec;
91}
92
93int
Denys Vlasenko12014262011-05-30 14:00:14 +020094tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095{
96 if (a->tv_sec < b->tv_sec
97 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
98 return -1;
99 if (a->tv_sec > b->tv_sec
100 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
101 return 1;
102 return 0;
103}
104
105double
Denys Vlasenko12014262011-05-30 14:00:14 +0200106tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107{
108 return tv->tv_sec + tv->tv_usec/1000000.0;
109}
110
111void
Denys Vlasenko12014262011-05-30 14:00:14 +0200112tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113{
114 tv->tv_sec = a->tv_sec + b->tv_sec;
115 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000116 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117 tv->tv_sec++;
118 tv->tv_usec -= 1000000;
119 }
120}
121
122void
Denys Vlasenko12014262011-05-30 14:00:14 +0200123tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124{
125 tv->tv_sec = a->tv_sec - b->tv_sec;
126 tv->tv_usec = a->tv_usec - b->tv_usec;
127 if (((long) tv->tv_usec) < 0) {
128 tv->tv_sec--;
129 tv->tv_usec += 1000000;
130 }
131}
132
133void
Denys Vlasenko12014262011-05-30 14:00:14 +0200134tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135{
136 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
137 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
138 tv->tv_usec %= 1000000;
139}
140
141void
Denys Vlasenko12014262011-05-30 14:00:14 +0200142tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143{
144 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000145 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146 tv->tv_usec %= 1000000;
147}
148
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000149const char *
150xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151{
152 for (; xlat->str != NULL; xlat++)
153 if (xlat->val == val)
154 return xlat->str;
155 return NULL;
156}
157
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200158#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200159char *
160stpcpy(char *dst, const char *src)
161{
162 while ((*dst = *src++) != '\0')
163 dst++;
164 return dst;
165}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200166#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200167
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168/*
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000169 * Used when we want to unblock stopped traced process.
170 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
171 * Returns 0 on success or if error was ESRCH
172 * (presumably process was killed while we talk to it).
173 * Otherwise prints error message and returns -1.
174 */
175int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700176ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000177{
178 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700179 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000180
181 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100182 ptrace(op, tcp->pid, (void *) 0, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000183 err = errno;
184 if (!err || err == ESRCH)
185 return 0;
186
187 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700188 msg = "SYSCALL";
189 if (op == PTRACE_CONT)
190 msg = "CONT";
191 if (op == PTRACE_DETACH)
192 msg = "DETACH";
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100193#ifdef PTRACE_LISTEN
194 if (op == PTRACE_LISTEN)
195 msg = "LISTEN";
196#endif
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100197 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000198 return -1;
199}
200
201/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 * Print entry in struct xlat table, if there.
203 */
204void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000205printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000207 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208
209 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200210 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211 else
212 tprintf("%#x /* %s */", val, dflt);
213}
214
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100215#if HAVE_LONG_LONG
216/*
217 * Print 64bit argument at position llarg and return the index of the next
218 * argument.
219 */
220int
221printllval(struct tcb *tcp, const char *format, int llarg)
222{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100223# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100224 if (current_personality == 0) {
225 tprintf(format, tcp->u_arg[llarg]);
226 llarg++;
227 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200228# ifdef POWERPC64
229 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200230 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200231# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100232 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
233 llarg += 2;
234 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200235# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100236 tprintf(format, tcp->u_arg[llarg]);
237 llarg++;
238# elif defined LINUX_MIPSN32
239 tprintf(format, tcp->ext_arg[llarg]);
240 llarg++;
241# else
242 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
243 llarg += 2;
244# endif
245 return llarg;
246}
247#endif
248
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249/*
250 * Interpret `xlat' as an array of flags
251 * print the entries whose bits are on in `flags'
252 * return # of flags printed.
253 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200254void
Denys Vlasenko12014262011-05-30 14:00:14 +0200255addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200257 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000258 if (xlat->val && (flags & xlat->val) == xlat->val) {
259 tprintf("|%s", xlat->str);
260 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000261 }
262 }
263 if (flags) {
264 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000266}
267
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000268/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200269 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000270 * Print to static string the entries whose bits are on in `flags'
271 * Return static string.
272 */
273const char *
274sprintflags(const char *prefix, const struct xlat *xlat, int flags)
275{
276 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200277 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000278 int found = 0;
279
Denys Vlasenko52845572011-08-31 12:07:38 +0200280 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000281
282 for (; xlat->str; xlat++) {
283 if ((flags & xlat->val) == xlat->val) {
284 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200285 *outptr++ = '|';
286 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000287 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100288 flags &= ~xlat->val;
289 if (!flags)
290 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000291 }
292 }
293 if (flags) {
294 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200295 *outptr++ = '|';
296 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000297 }
298
299 return outstr;
300}
301
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000303printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304{
305 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000306 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307
308 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200309 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310 return 1;
311 }
312
313 sep = "";
314 for (n = 0; xlat->str; xlat++) {
315 if (xlat->val && (flags & xlat->val) == xlat->val) {
316 tprintf("%s%s", sep, xlat->str);
317 flags &= ~xlat->val;
318 sep = "|";
319 n++;
320 }
321 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000322
323 if (n) {
324 if (flags) {
325 tprintf("%s%#x", sep, flags);
326 n++;
327 }
328 } else {
329 if (flags) {
330 tprintf("%#x", flags);
331 if (dflt)
332 tprintf(" /* %s */", dflt);
333 } else {
334 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200335 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000336 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000338
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339 return n;
340}
341
342void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000343printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000344{
Roland McGratheb285352003-01-14 09:59:00 +0000345 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346
347 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200348 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000349 return;
350 }
351 if (umove(tcp, addr, &num) < 0) {
352 tprintf("%#lx", addr);
353 return;
354 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200355 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200357 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000358}
359
Roland McGrath6bc12202003-11-13 22:32:27 +0000360void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000361printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000362{
363 int num;
364
365 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200366 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000367 return;
368 }
369 if (umove(tcp, addr, &num) < 0) {
370 tprintf("%#lx", addr);
371 return;
372 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200373 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000374 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200375 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000376}
377
378void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300379printfd(struct tcb *tcp, int fd)
380{
Grant Edwards8a082772011-04-07 20:25:40 +0000381 const char *p;
382
383 if (show_fd_path && (p = getfdpath(tcp, fd)))
384 tprintf("%d<%s>", fd, p);
385 else
386 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300387}
388
389void
Denys Vlasenko12014262011-05-30 14:00:14 +0200390printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000391{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200392 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000393}
394
Dmitry V. Levina501f142008-11-10 23:19:13 +0000395/*
396 * Quote string `instr' of length `size'
397 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
398 * If `len' < 0, treat `instr' as a NUL-terminated string
399 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100400 *
401 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
402 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000403 */
Roland McGrath6d970322007-11-01 23:53:59 +0000404static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000405string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000406{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000407 const unsigned char *ustr = (const unsigned char *) instr;
408 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200409 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200411 eol = 0x100; /* this can never match a char */
412 if (len < 0) {
413 size--;
414 eol = '\0';
415 }
416
417 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000418 if (xflag > 1)
419 usehex = 1;
420 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000421 /* Check for presence of symbol which require
422 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423 for (i = 0; i < size; ++i) {
424 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000425 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200426 if (c == eol)
427 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000428 if (!isprint(c) && !isspace(c)) {
429 usehex = 1;
430 break;
431 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000432 }
433 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000434
435 *s++ = '\"';
436
437 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000438 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000439 for (i = 0; i < size; ++i) {
440 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000441 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200442 if (c == eol)
443 goto asciz_ended;
444 *s++ = '\\';
445 *s++ = 'x';
446 *s++ = "0123456789abcdef"[c >> 4];
447 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000448 }
449 } else {
450 for (i = 0; i < size; ++i) {
451 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000452 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200453 if (c == eol)
454 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000455 switch (c) {
456 case '\"': case '\\':
457 *s++ = '\\';
458 *s++ = c;
459 break;
460 case '\f':
461 *s++ = '\\';
462 *s++ = 'f';
463 break;
464 case '\n':
465 *s++ = '\\';
466 *s++ = 'n';
467 break;
468 case '\r':
469 *s++ = '\\';
470 *s++ = 'r';
471 break;
472 case '\t':
473 *s++ = '\\';
474 *s++ = 't';
475 break;
476 case '\v':
477 *s++ = '\\';
478 *s++ = 'v';
479 break;
480 default:
481 if (isprint(c))
482 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200483 else {
484 /* Print \octal */
485 *s++ = '\\';
486 if (i + 1 < size
487 && ustr[i + 1] >= '0'
488 && ustr[i + 1] <= '9'
489 ) {
490 /* Print \ooo */
491 *s++ = '0' + (c >> 6);
492 *s++ = '0' + ((c >> 3) & 0x7);
493 } else {
494 /* Print \[[o]o]o */
495 if ((c >> 3) != 0) {
496 if ((c >> 6) != 0)
497 *s++ = '0' + (c >> 6);
498 *s++ = '0' + ((c >> 3) & 0x7);
499 }
500 }
501 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000502 }
503 break;
504 }
505 }
506 }
507
508 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000510
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200511 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
512 if (len < 0 && ustr[i] == '\0') {
513 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
514 * but next char is NUL.
515 */
516 return 0;
517 }
518
519 return 1;
520
521 asciz_ended:
522 *s++ = '\"';
523 *s = '\0';
524 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
525 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526}
527
Dmitry V. Levina501f142008-11-10 23:19:13 +0000528/*
529 * Print path string specified by address `addr' and length `n'.
530 * If path length exceeds `n', append `...' to the output.
531 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000533printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100535 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100536 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100537
Dmitry V. Levina501f142008-11-10 23:19:13 +0000538 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200539 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000540 return;
541 }
542
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100543 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000544 if (n > sizeof path - 1)
545 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000546
547 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100548 nul_seen = umovestr(tcp, addr, n + 1, path);
549 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550 tprintf("%#lx", addr);
551 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100552 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100554 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100555 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100556 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100557 string_quote(path, outstr, -1, n);
558 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100559 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100560 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 }
562}
563
564void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100567 /* Size must correspond to char path[] size in printpathn */
568 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000569}
570
Dmitry V. Levina501f142008-11-10 23:19:13 +0000571/*
572 * Print string specified by address `addr' and length `len'.
573 * If `len' < 0, treat the string as a NUL-terminated string.
574 * If string length exceeds `max_strlen', append `...' to the output.
575 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000576void
577printstr(struct tcb *tcp, long addr, int len)
578{
579 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000580 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000581 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100582 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000583
584 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200585 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000586 return;
587 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000588 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200589 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000590 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200591 if (!str)
592 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100593 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200594 if (!outstr)
595 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000597
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000599 /*
600 * Treat as a NUL-terminated string: fetch one byte more
601 * because string_quote() quotes one byte less.
602 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000603 size = max_strlen + 1;
604 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000605 tprintf("%#lx", addr);
606 return;
607 }
608 }
609 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000610 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000611 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612 tprintf("%#lx", addr);
613 return;
614 }
615 }
616
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100617 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
618 * or we were requested to print more than -s NUM chars)...
619 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100620 ellipsis = (string_quote(str, outstr, len, size) &&
621 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000622
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100623 tprints(outstr);
624 if (ellipsis)
625 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000626}
627
John Hughes1d08dcf2001-07-10 13:48:44 +0000628#if HAVE_SYS_UIO_H
629void
Denys Vlasenko12014262011-05-30 14:00:14 +0200630dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000631{
Denys Vlasenko84703742012-02-25 02:38:52 +0100632#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000633 union {
634 struct { u_int32_t base; u_int32_t len; } *iov32;
635 struct { u_int64_t base; u_int64_t len; } *iov64;
636 } iovu;
637#define iov iovu.iov64
638#define sizeof_iov \
639 (personality_wordsize[current_personality] == 4 \
640 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
641#define iov_iov_base(i) \
642 (personality_wordsize[current_personality] == 4 \
643 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
644#define iov_iov_len(i) \
645 (personality_wordsize[current_personality] == 4 \
646 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
647#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000648 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000649#define sizeof_iov sizeof(*iov)
650#define iov_iov_base(i) iov[i].iov_base
651#define iov_iov_len(i) iov[i].iov_len
652#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000653 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200654 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000655
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200656 size = sizeof_iov * len;
657 /* Assuming no sane program has millions of iovs */
658 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000659 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200660 fprintf(stderr, "Out of memory\n");
661 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000662 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000663 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000664 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000665 /* include the buffer number to make it easy to
666 * match up the trace with the source */
667 tprintf(" * %lu bytes in buffer %d\n",
668 (unsigned long)iov_iov_len(i), i);
669 dumpstr(tcp, (long) iov_iov_base(i),
670 iov_iov_len(i));
671 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000672 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200673 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000674#undef sizeof_iov
675#undef iov_iov_base
676#undef iov_iov_len
677#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000678}
679#endif
680
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681void
Denys Vlasenko12014262011-05-30 14:00:14 +0200682dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683{
684 static int strsize = -1;
685 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 char *s;
687 int i, j;
688
689 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200690 free(str);
691 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200692 if (!str) {
693 strsize = -1;
694 fprintf(stderr, "Out of memory\n");
695 return;
696 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 strsize = len;
698 }
699
700 if (umoven(tcp, addr, len, (char *) str) < 0)
701 return;
702
703 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200704 char outstr[80];
705
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000706 s = outstr;
707 sprintf(s, " | %05x ", i);
708 s += 9;
709 for (j = 0; j < 16; j++) {
710 if (j == 8)
711 *s++ = ' ';
712 if (i + j < len) {
713 sprintf(s, " %02x", str[i + j]);
714 s += 3;
715 }
716 else {
717 *s++ = ' '; *s++ = ' '; *s++ = ' ';
718 }
719 }
720 *s++ = ' '; *s++ = ' ';
721 for (j = 0; j < 16; j++) {
722 if (j == 8)
723 *s++ = ' ';
724 if (i + j < len) {
725 if (isprint(str[i + j]))
726 *s++ = str[i + j];
727 else
728 *s++ = '.';
729 }
730 else
731 *s++ = ' ';
732 }
733 tprintf("%s |\n", outstr);
734 }
735}
736
Mike Frysinger612659e2012-02-14 14:38:28 +0100737#ifdef HAVE_PROCESS_VM_READV
738/* C library supports this, but the kernel might not. */
739static bool process_vm_readv_not_supported = 0;
740#else
741
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100742/* Need to do this since process_vm_readv() is not yet available in libc.
743 * When libc is be updated, only "static bool process_vm_readv_not_supported"
744 * line should remain.
745 */
746#if !defined(__NR_process_vm_readv)
747# if defined(I386)
748# define __NR_process_vm_readv 347
749# elif defined(X86_64)
750# define __NR_process_vm_readv 310
751# elif defined(POWERPC)
752# define __NR_process_vm_readv 351
753# endif
754#endif
755
756#if defined(__NR_process_vm_readv)
757static bool process_vm_readv_not_supported = 0;
758static ssize_t process_vm_readv(pid_t pid,
759 const struct iovec *lvec,
760 unsigned long liovcnt,
761 const struct iovec *rvec,
762 unsigned long riovcnt,
763 unsigned long flags)
764{
765 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
766}
767#else
768static bool process_vm_readv_not_supported = 1;
769# define process_vm_readv(...) (errno = ENOSYS, -1)
770#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100771
772#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100773
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774#define PAGMASK (~(PAGSIZ - 1))
775/*
776 * move `len' bytes of data from process `pid'
777 * at address `addr' to our space at `laddr'
778 */
779int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000780umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700782 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100784 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 union {
786 long val;
787 char x[sizeof(long)];
788 } u;
789
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100790#if SUPPORTED_PERSONALITIES > 1
791 if (personality_wordsize[current_personality] < sizeof(addr))
792 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
793#endif
794
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100795 if (!process_vm_readv_not_supported) {
796 struct iovec local[1], remote[1];
797 int r;
798
799 local[0].iov_base = laddr;
800 remote[0].iov_base = (void*)addr;
801 local[0].iov_len = remote[0].iov_len = len;
802 r = process_vm_readv(pid,
803 local, 1,
804 remote, 1,
805 /*flags:*/ 0
806 );
807 if (r < 0) {
808 if (errno == ENOSYS)
809 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100810 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
811 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100812 perror("process_vm_readv");
813 goto vm_readv_didnt_work;
814 }
815 return r;
816 }
817 vm_readv_didnt_work:
818
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100819 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820 if (addr & (sizeof(long) - 1)) {
821 /* addr not a multiple of sizeof(long) */
822 n = addr - (addr & -sizeof(long)); /* residue */
823 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700824 errno = 0;
825 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
826 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700827 /* But if not started, we had a bogus address. */
828 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100829 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700830 return -1;
831 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000832 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100833 m = MIN(sizeof(long) - n, len);
834 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000835 addr += sizeof(long), laddr += m, len -= m;
836 }
837 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700838 errno = 0;
839 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
840 if (errno) {
841 if (started && (errno==EPERM || errno==EIO)) {
842 /* Ran into 'end of memory' - stupid "printpath" */
843 return 0;
844 }
845 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100846 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700847 return -1;
848 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000849 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100850 m = MIN(sizeof(long), len);
851 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852 addr += sizeof(long), laddr += m, len -= m;
853 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000854
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000855 return 0;
856}
857
858/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100859 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000860 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100861 *
862 * Returns < 0 on error, > 0 if NUL was seen,
863 * (TODO if useful: return count of bytes including NUL),
864 * else 0 if len bytes were read but no NUL byte seen.
865 *
866 * Note: there is no guarantee we won't overwrite some bytes
867 * in laddr[] _after_ terminating NUL (but, of course,
868 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000869 */
870int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000871umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100873 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700874 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000875 int i, n, m;
876 union {
877 long val;
878 char x[sizeof(long)];
879 } u;
880
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000881#if SUPPORTED_PERSONALITIES > 1
882 if (personality_wordsize[current_personality] < sizeof(addr))
883 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
884#endif
885
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100886 if (!process_vm_readv_not_supported) {
887 struct iovec local[1], remote[1];
888
889 local[0].iov_base = laddr;
890 remote[0].iov_base = (void*)addr;
891
892 while (len > 0) {
893 int end_in_page;
894 int r;
895 int chunk_len;
896
897 /* Don't read kilobytes: most strings are short */
898 chunk_len = len;
899 if (chunk_len > 256)
900 chunk_len = 256;
901 /* Don't cross pages. I guess otherwise we can get EFAULT
902 * and fail to notice that terminating NUL lies
903 * in the existing (first) page.
904 * (I hope there aren't arches with pages < 4K)
905 */
906 end_in_page = ((addr + chunk_len) & 4095);
907 r = chunk_len - end_in_page;
908 if (r > 0) /* if chunk_len > end_in_page */
909 chunk_len = r; /* chunk_len -= end_in_page */
910
911 local[0].iov_len = remote[0].iov_len = chunk_len;
912 r = process_vm_readv(pid,
913 local, 1,
914 remote, 1,
915 /*flags:*/ 0
916 );
917 if (r < 0) {
918 if (errno == ENOSYS)
919 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100920 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
921 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100922 perror("process_vm_readv");
923 goto vm_readv_didnt_work;
924 }
925 if (memchr(local[0].iov_base, '\0', r))
926 return 1;
927 local[0].iov_base += r;
928 remote[0].iov_base += r;
929 len -= r;
930 }
931 return 0;
932 }
933 vm_readv_didnt_work:
934
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100935 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936 if (addr & (sizeof(long) - 1)) {
937 /* addr not a multiple of sizeof(long) */
938 n = addr - (addr & -sizeof(long)); /* residue */
939 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700940 errno = 0;
941 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
942 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700943 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100944 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700945 return -1;
946 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000947 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100948 m = MIN(sizeof(long) - n, len);
949 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950 while (n & (sizeof(long) - 1))
951 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100952 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 addr += sizeof(long), laddr += m, len -= m;
954 }
955 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700956 errno = 0;
957 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
958 if (errno) {
959 if (started && (errno==EPERM || errno==EIO)) {
960 /* Ran into 'end of memory' - stupid "printpath" */
961 return 0;
962 }
963 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100964 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700965 return -1;
966 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000967 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100968 m = MIN(sizeof(long), len);
969 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 for (i = 0; i < sizeof(long); i++)
971 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100972 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 addr += sizeof(long), laddr += m, len -= m;
974 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000975 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976}
977
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100978#if !defined(SPARC) && !defined(SPARC64)
979# define PTRACE_WRITETEXT 101
980# define PTRACE_WRITEDATA 102
981#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982
983int
Denys Vlasenko12014262011-05-30 14:00:14 +0200984upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985{
986 long val;
987
Roland McGratheb9e2e82009-06-02 16:49:22 -0700988 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100989 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700990 if (val == -1 && errno) {
991 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100992 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700993 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700995 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 *res = val;
997 return 0;
998}
999
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001001printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002{
Roland McGrath7a918832005-02-02 20:55:23 +00001003#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1004 sizeof(long) == 8 ? "[????????????????] " : \
1005 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001007#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 long eip;
1009
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001010 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001011 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 return;
1013 }
1014 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001015
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001016#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001017 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001018 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001019 PRINTBADPC;
1020 return;
1021 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001022# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001023 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001024# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001025 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001026# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001027
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001028#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001029 long rip;
1030
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001031 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001032 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001033 return;
1034 }
1035 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001036#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001037 long ip;
1038
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001039 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001040 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001041 return;
1042 }
1043 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001044#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 long pc;
1046
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001047 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001048 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 return;
1050 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001051# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001052 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001053# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001055# endif
1056#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 long pc;
1058
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001059 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001060 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061 return;
1062 }
1063 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001064#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 long pc;
1066
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001067 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001068 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 return;
1070 }
1071 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001072#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001073 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001074 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001075 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 return;
1077 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001078# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001079 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001080# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001081 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001082# endif
1083#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001084 long pc;
1085
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001086 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001087 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001088 return;
1089 }
1090 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001091#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001092 long pc;
1093
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001095 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001096 return;
1097 }
1098 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001099#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001100 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001101
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001102 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001103 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001104 return;
1105 }
1106 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001107#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001108 long pc;
1109
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001110 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001111 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001112 return;
1113 }
1114 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001115#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001116 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001117
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001118 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001119 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001120 return;
1121 }
1122 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001123#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001124 long pc;
1125
1126 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001127 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001128 return;
1129 }
1130 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001131#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001132 long pc;
1133
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001134 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001135 PRINTBADPC;
1136 return;
1137 }
1138 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001139#elif defined(CRISV10)
1140 long pc;
1141
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001142 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001143 PRINTBADPC;
1144 return;
1145 }
1146 tprintf("[%08lx] ", pc);
1147#elif defined(CRISV32)
1148 long pc;
1149
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001150 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001151 PRINTBADPC;
1152 return;
1153 }
1154 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001155#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156}
1157
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001158/*
1159 * These #if's are huge, please indent them correctly.
1160 * It's easy to get confused otherwise.
1161 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001163#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001164
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001165#include <sys/syscall.h>
1166#ifndef CLONE_PTRACE
1167# define CLONE_PTRACE 0x00002000
1168#endif
1169#ifndef CLONE_VFORK
1170# define CLONE_VFORK 0x00004000
1171#endif
1172#ifndef CLONE_VM
1173# define CLONE_VM 0x00000100
1174#endif
1175#ifndef CLONE_STOPPED
1176# define CLONE_STOPPED 0x02000000
1177#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001178
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001179#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180
1181typedef unsigned long *arg_setup_state;
1182
1183static int
1184arg_setup(struct tcb *tcp, arg_setup_state *state)
1185{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001186 unsigned long cfm, sof, sol;
1187 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001188
Jan Kratochvil1f942712008-08-06 21:38:52 +00001189 if (ia32) {
1190 /* Satisfy a false GCC warning. */
1191 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001192 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001193 }
Roland McGrath08267b82004-02-20 22:56:43 +00001194
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001195 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001196 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001197 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001198 return -1;
1199
1200 sof = (cfm >> 0) & 0x7f;
1201 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001202 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001203
Jan Kratochvil1f942712008-08-06 21:38:52 +00001204 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001205 return 0;
1206}
1207
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001208# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001209
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001211get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001212{
Roland McGrath08267b82004-02-20 22:56:43 +00001213 int ret;
1214
1215 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001216 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001217 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001218 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001219 (unsigned long) ia64_rse_skip_regs(*state, 0),
1220 sizeof(long), (void *) valp);
1221 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001222}
1223
1224static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001225get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226{
Roland McGrath08267b82004-02-20 22:56:43 +00001227 int ret;
1228
1229 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001230 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001231 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001232 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001233 (unsigned long) ia64_rse_skip_regs(*state, 1),
1234 sizeof(long), (void *) valp);
1235 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001236}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001237
1238static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001239set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001240{
Roland McGrath08267b82004-02-20 22:56:43 +00001241 int req = PTRACE_POKEDATA;
1242 void *ap;
1243
1244 if (ia32) {
1245 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1246 req = PTRACE_POKEUSER;
1247 } else
1248 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001249 errno = 0;
1250 ptrace(req, tcp->pid, ap, val);
1251 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252}
1253
1254static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001255set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001256{
Roland McGrath08267b82004-02-20 22:56:43 +00001257 int req = PTRACE_POKEDATA;
1258 void *ap;
1259
1260 if (ia32) {
1261 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1262 req = PTRACE_POKEUSER;
1263 } else
1264 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001265 errno = 0;
1266 ptrace(req, tcp->pid, ap, val);
1267 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268}
1269
Roland McGrathb659f872008-07-18 01:19:36 +00001270/* ia64 does not return the input arguments from functions (and syscalls)
1271 according to ia64 RSE (Register Stack Engine) behavior. */
1272
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001273# define restore_arg0(tcp, state, val) ((void) (state), 0)
1274# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001275
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001276#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277
Mike Frysinger8566c502009-10-12 11:05:14 -04001278typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001280# define arg_setup(tcp, state) \
1281 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1282# define arg_finish_change(tcp, state) \
1283 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001285# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1286# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1287# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1288# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1289# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001291#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001293# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001294/* Note: this is only true for the `clone' system call, which handles
1295 arguments specially. We could as well say that its first two arguments
1296 are swapped relative to other architectures, but that would just be
1297 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001298# define arg0_offset PT_GPR3
1299# define arg1_offset PT_ORIGGPR2
1300# define restore_arg0(tcp, state, val) ((void) (state), 0)
1301# define restore_arg1(tcp, state, val) ((void) (state), 0)
1302# define arg0_index 1
1303# define arg1_index 0
1304# elif defined(ALPHA) || defined(MIPS)
1305# define arg0_offset REG_A0
1306# define arg1_offset (REG_A0+1)
1307# elif defined(AVR32)
1308# define arg0_offset (REG_R12)
1309# define arg1_offset (REG_R11)
1310# elif defined(POWERPC)
1311# define arg0_offset (sizeof(unsigned long)*PT_R3)
1312# define arg1_offset (sizeof(unsigned long)*PT_R4)
1313# define restore_arg0(tcp, state, val) ((void) (state), 0)
1314# elif defined(HPPA)
1315# define arg0_offset PT_GR26
1316# define arg1_offset (PT_GR26-4)
1317# elif defined(X86_64)
1318# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1319# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1320# elif defined(SH)
1321# define arg0_offset (4*(REG_REG0+4))
1322# define arg1_offset (4*(REG_REG0+5))
1323# elif defined(SH64)
1324 /* ABI defines arg0 & 1 in r2 & r3 */
1325# define arg0_offset (REG_OFFSET+16)
1326# define arg1_offset (REG_OFFSET+24)
1327# define restore_arg0(tcp, state, val) 0
1328# elif defined CRISV10 || defined CRISV32
1329# define arg0_offset (4*PT_R11)
1330# define arg1_offset (4*PT_ORIG_R10)
1331# define restore_arg0(tcp, state, val) 0
1332# define restore_arg1(tcp, state, val) 0
1333# define arg0_index 1
1334# define arg1_index 0
1335# else
1336# define arg0_offset 0
1337# define arg1_offset 4
1338# if defined ARM
1339# define restore_arg0(tcp, state, val) 0
1340# endif
1341# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342
1343typedef int arg_setup_state;
1344
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001345# define arg_setup(tcp, state) (0)
1346# define arg_finish_change(tcp, state) 0
1347# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1348# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349
1350static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001351set_arg0(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*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001354}
1355
1356static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001357set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001359 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360}
1361
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001362#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001363
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001364#ifndef restore_arg0
1365# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1366#endif
1367#ifndef restore_arg1
1368# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1369#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001370
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001371#ifndef arg0_index
1372# define arg0_index 0
1373# define arg1_index 1
1374#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001375
Roland McGrathd81f1d92003-01-09 06:53:34 +00001376int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001377setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001378{
Roland McGrath3291ef22008-05-20 00:34:34 +00001379 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380 arg_setup_state state;
1381
1382 if (tcp->flags & TCB_BPTSET) {
1383 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1384 return -1;
1385 }
1386
Roland McGrath3291ef22008-05-20 00:34:34 +00001387 /*
1388 * It's a silly kludge to initialize this with a search at runtime.
1389 * But it's better than maintaining another magic thing in the
1390 * godforsaken tables.
1391 */
1392 if (clone_scno[current_personality] == 0) {
1393 int i;
1394 for (i = 0; i < nsyscalls; ++i)
1395 if (sysent[i].sys_func == sys_clone) {
1396 clone_scno[current_personality] = i;
1397 break;
1398 }
1399 }
1400
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001401 if (sysent[tcp->scno].sys_func == sys_fork ||
1402 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001403 if (arg_setup(tcp, &state) < 0
1404 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1405 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001406 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001407 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1408 || set_arg1(tcp, &state, 0) < 0
1409 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001410 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001411 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1412 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413 tcp->flags |= TCB_BPTSET;
1414 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001415 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001416
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001417 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001418 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001419 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001420 vfork semantics into plain fork - each application must not
1421 depend on the vfork specifics according to POSIX. We would
1422 hang waiting for the parent resume otherwise. We need to
1423 clear also CLONE_VM but only in the CLONE_VFORK case as
1424 otherwise we would break pthread_create. */
1425
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001426 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1427 if (new_arg0 & CLONE_VFORK)
1428 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1429 if (arg_setup(tcp, &state) < 0
1430 || set_arg0(tcp, &state, new_arg0) < 0
1431 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001432 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001433 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001434 tcp->inst[0] = tcp->u_arg[arg0_index];
1435 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001436 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437 }
1438
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001439 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1440 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001441 return -1;
1442}
1443
1444int
Denys Vlasenko12014262011-05-30 14:00:14 +02001445clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001446{
1447 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001448 if (arg_setup(tcp, &state) < 0
1449 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1450 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1451 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001452 if (errno != ESRCH)
1453 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001454 tcp->flags &= ~TCB_BPTSET;
1455 return 0;
1456}