blob: f6e62e9d32c666dffb36a93a12cd12a2c6a151bd [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 defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000043# include <asm/ptrace_offsets.h>
44# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000045#endif
46
Wichert Akkerman36915a11999-07-13 15:45:02 +000047#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010048# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010051# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010058# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000059# undef ia64_fpreg
60# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000061#endif
62
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063/* macros */
64#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010065# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000066#endif
67#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010068# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000072string_to_uint(const char *str)
73{
74 char *error;
75 long value;
76
77 if (!*str)
78 return -1;
79 errno = 0;
80 value = strtol(str, &error, 10);
81 if (errno || *error || value < 0 || (long)(int)value != value)
82 return -1;
83 return (int)value;
84}
85
86int
Denys Vlasenko12014262011-05-30 14:00:14 +020087tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088{
89 return a->tv_sec || a->tv_usec;
90}
91
92int
Denys Vlasenko12014262011-05-30 14:00:14 +020093tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094{
95 if (a->tv_sec < b->tv_sec
96 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
97 return -1;
98 if (a->tv_sec > b->tv_sec
99 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
100 return 1;
101 return 0;
102}
103
104double
Denys Vlasenko12014262011-05-30 14:00:14 +0200105tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106{
107 return tv->tv_sec + tv->tv_usec/1000000.0;
108}
109
110void
Denys Vlasenko12014262011-05-30 14:00:14 +0200111tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112{
113 tv->tv_sec = a->tv_sec + b->tv_sec;
114 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000115 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116 tv->tv_sec++;
117 tv->tv_usec -= 1000000;
118 }
119}
120
121void
Denys Vlasenko12014262011-05-30 14:00:14 +0200122tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123{
124 tv->tv_sec = a->tv_sec - b->tv_sec;
125 tv->tv_usec = a->tv_usec - b->tv_usec;
126 if (((long) tv->tv_usec) < 0) {
127 tv->tv_sec--;
128 tv->tv_usec += 1000000;
129 }
130}
131
132void
Denys Vlasenko12014262011-05-30 14:00:14 +0200133tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134{
135 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
136 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
137 tv->tv_usec %= 1000000;
138}
139
140void
Denys Vlasenko12014262011-05-30 14:00:14 +0200141tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142{
143 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000144 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145 tv->tv_usec %= 1000000;
146}
147
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000148const char *
149xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150{
151 for (; xlat->str != NULL; xlat++)
152 if (xlat->val == val)
153 return xlat->str;
154 return NULL;
155}
156
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200157#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200158char *
159stpcpy(char *dst, const char *src)
160{
161 while ((*dst = *src++) != '\0')
162 dst++;
163 return dst;
164}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200165#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200166
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167/*
168 * Print entry in struct xlat table, if there.
169 */
170void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000171printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000173 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200176 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177 else
178 tprintf("%#x /* %s */", val, dflt);
179}
180
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100181/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100182 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100183 * argument.
184 */
185int
Chris Metcalf879dddd2013-03-01 10:41:02 +0100186printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100187{
Chris Metcalf879dddd2013-03-01 10:41:02 +0100188#if defined(X86_64) || defined(POWERPC64) || defined(TILE)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100189 if (current_personality == 0) {
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100190 /* Technically, format expects "long long",
191 * but we supply "long". We expect that
192 * on this arch, they are the same.
193 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100194 tprintf(format, tcp->u_arg[arg_no]);
195 arg_no++;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100196 } else {
Chris Metcalf879dddd2013-03-01 10:41:02 +0100197# if defined(POWERPC64)
198 /* Align arg_no to next even number */
199 arg_no = (arg_no + 1) & 0xe;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100200# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100201 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
202 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100203 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100204#elif defined IA64 || defined ALPHA
205 /* Technically, format expects "long long",
206 * but we supply "long". We expect that
207 * on this arch, they are the same.
208 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100209 tprintf(format, tcp->u_arg[arg_no]);
210 arg_no++;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100211#elif defined LINUX_MIPSN32 || defined X32
Chris Metcalf879dddd2013-03-01 10:41:02 +0100212 tprintf(format, tcp->ext_arg[arg_no]);
213 arg_no++;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100214#else
215# if SIZEOF_LONG > 4
216# error BUG: must not combine two args for long long on this arch
217# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100218 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
219 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100220#endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100221 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100222}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100223
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000224/*
225 * Interpret `xlat' as an array of flags
226 * print the entries whose bits are on in `flags'
227 * return # of flags printed.
228 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200229void
Denys Vlasenko12014262011-05-30 14:00:14 +0200230addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200232 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 if (xlat->val && (flags & xlat->val) == xlat->val) {
234 tprintf("|%s", xlat->str);
235 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 }
237 }
238 if (flags) {
239 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241}
242
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000243/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200244 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000245 * Print to static string the entries whose bits are on in `flags'
246 * Return static string.
247 */
248const char *
249sprintflags(const char *prefix, const struct xlat *xlat, int flags)
250{
251 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200252 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253 int found = 0;
254
Denys Vlasenko52845572011-08-31 12:07:38 +0200255 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000256
257 for (; xlat->str; xlat++) {
258 if ((flags & xlat->val) == xlat->val) {
259 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200260 *outptr++ = '|';
261 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000262 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100263 flags &= ~xlat->val;
264 if (!flags)
265 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000266 }
267 }
268 if (flags) {
269 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200270 *outptr++ = '|';
271 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000272 }
273
274 return outstr;
275}
276
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000278printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000279{
280 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000281 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282
283 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200284 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000285 return 1;
286 }
287
288 sep = "";
289 for (n = 0; xlat->str; xlat++) {
290 if (xlat->val && (flags & xlat->val) == xlat->val) {
291 tprintf("%s%s", sep, xlat->str);
292 flags &= ~xlat->val;
293 sep = "|";
294 n++;
295 }
296 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000297
298 if (n) {
299 if (flags) {
300 tprintf("%s%#x", sep, flags);
301 n++;
302 }
303 } else {
304 if (flags) {
305 tprintf("%#x", flags);
306 if (dflt)
307 tprintf(" /* %s */", dflt);
308 } else {
309 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200310 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000311 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314 return n;
315}
316
317void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000318printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
Roland McGratheb285352003-01-14 09:59:00 +0000320 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321
322 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200323 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324 return;
325 }
326 if (umove(tcp, addr, &num) < 0) {
327 tprintf("%#lx", addr);
328 return;
329 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200330 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200332 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333}
334
Roland McGrath6bc12202003-11-13 22:32:27 +0000335void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000336printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000337{
338 int num;
339
340 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200341 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000342 return;
343 }
344 if (umove(tcp, addr, &num) < 0) {
345 tprintf("%#lx", addr);
346 return;
347 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200348 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000349 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200350 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000351}
352
353void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300354printfd(struct tcb *tcp, int fd)
355{
Grant Edwards8a082772011-04-07 20:25:40 +0000356 const char *p;
357
358 if (show_fd_path && (p = getfdpath(tcp, fd)))
359 tprintf("%d<%s>", fd, p);
360 else
361 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300362}
363
364void
Denys Vlasenko12014262011-05-30 14:00:14 +0200365printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000366{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200367 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000368}
369
Dmitry V. Levina501f142008-11-10 23:19:13 +0000370/*
371 * Quote string `instr' of length `size'
372 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200373 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000374 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100375 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200376 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100377 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000378 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400379int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200380string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000382 const unsigned char *ustr = (const unsigned char *) instr;
383 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200384 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200386 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200387 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200388 size--;
389 eol = '\0';
390 }
391
392 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000393 if (xflag > 1)
394 usehex = 1;
395 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000396 /* Check for presence of symbol which require
397 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000398 for (i = 0; i < size; ++i) {
399 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000400 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200401 if (c == eol)
402 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000403 if (!isprint(c) && !isspace(c)) {
404 usehex = 1;
405 break;
406 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 }
408 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000409
410 *s++ = '\"';
411
412 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000413 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000414 for (i = 0; i < size; ++i) {
415 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000416 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200417 if (c == eol)
418 goto asciz_ended;
419 *s++ = '\\';
420 *s++ = 'x';
421 *s++ = "0123456789abcdef"[c >> 4];
422 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423 }
424 } else {
425 for (i = 0; i < size; ++i) {
426 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000427 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200428 if (c == eol)
429 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000430 switch (c) {
431 case '\"': case '\\':
432 *s++ = '\\';
433 *s++ = c;
434 break;
435 case '\f':
436 *s++ = '\\';
437 *s++ = 'f';
438 break;
439 case '\n':
440 *s++ = '\\';
441 *s++ = 'n';
442 break;
443 case '\r':
444 *s++ = '\\';
445 *s++ = 'r';
446 break;
447 case '\t':
448 *s++ = '\\';
449 *s++ = 't';
450 break;
451 case '\v':
452 *s++ = '\\';
453 *s++ = 'v';
454 break;
455 default:
456 if (isprint(c))
457 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200458 else {
459 /* Print \octal */
460 *s++ = '\\';
461 if (i + 1 < size
462 && ustr[i + 1] >= '0'
463 && ustr[i + 1] <= '9'
464 ) {
465 /* Print \ooo */
466 *s++ = '0' + (c >> 6);
467 *s++ = '0' + ((c >> 3) & 0x7);
468 } else {
469 /* Print \[[o]o]o */
470 if ((c >> 3) != 0) {
471 if ((c >> 6) != 0)
472 *s++ = '0' + (c >> 6);
473 *s++ = '0' + ((c >> 3) & 0x7);
474 }
475 }
476 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000477 }
478 break;
479 }
480 }
481 }
482
483 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000485
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200486 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200487 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200488 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
489 * but next char is NUL.
490 */
491 return 0;
492 }
493
494 return 1;
495
496 asciz_ended:
497 *s++ = '\"';
498 *s = '\0';
499 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
500 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501}
502
Dmitry V. Levina501f142008-11-10 23:19:13 +0000503/*
504 * Print path string specified by address `addr' and length `n'.
505 * If path length exceeds `n', append `...' to the output.
506 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000508printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100510 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100511 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100512
Dmitry V. Levina501f142008-11-10 23:19:13 +0000513 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200514 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000515 return;
516 }
517
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100518 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000519 if (n > sizeof path - 1)
520 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000521
522 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100523 nul_seen = umovestr(tcp, addr, n + 1, path);
524 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525 tprintf("%#lx", addr);
526 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100527 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100529 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100530 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100531 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100532 string_quote(path, outstr, -1, n);
533 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100534 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100535 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 }
537}
538
539void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000540printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000541{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100542 /* Size must correspond to char path[] size in printpathn */
543 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000544}
545
Dmitry V. Levina501f142008-11-10 23:19:13 +0000546/*
547 * Print string specified by address `addr' and length `len'.
548 * If `len' < 0, treat the string as a NUL-terminated string.
549 * If string length exceeds `max_strlen', append `...' to the output.
550 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000551void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200552printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553{
554 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000556 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100557 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558
559 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200560 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 return;
562 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000563 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200564 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000565 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
566
567 if (outstr_size / 4 != max_strlen)
568 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200570 if (!str)
571 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000572 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200573 if (!outstr)
574 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000576
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200577 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000578 /*
579 * Treat as a NUL-terminated string: fetch one byte more
580 * because string_quote() quotes one byte less.
581 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000582 size = max_strlen + 1;
583 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 tprintf("%#lx", addr);
585 return;
586 }
587 }
588 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200589 size = max_strlen;
590 if (size > (unsigned long)len)
591 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000592 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593 tprintf("%#lx", addr);
594 return;
595 }
596 }
597
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100598 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
599 * or we were requested to print more than -s NUM chars)...
600 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100601 ellipsis = (string_quote(str, outstr, len, size) &&
602 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000603
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100604 tprints(outstr);
605 if (ellipsis)
606 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607}
608
John Hughes1d08dcf2001-07-10 13:48:44 +0000609#if HAVE_SYS_UIO_H
610void
Denys Vlasenko12014262011-05-30 14:00:14 +0200611dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000612{
Denys Vlasenko84703742012-02-25 02:38:52 +0100613#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000614 union {
615 struct { u_int32_t base; u_int32_t len; } *iov32;
616 struct { u_int64_t base; u_int64_t len; } *iov64;
617 } iovu;
618#define iov iovu.iov64
619#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100620 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000621#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100622 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000623#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100624 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000625#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000626 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000627#define sizeof_iov sizeof(*iov)
628#define iov_iov_base(i) iov[i].iov_base
629#define iov_iov_len(i) iov[i].iov_len
630#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000631 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200632 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000633
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200634 size = sizeof_iov * len;
635 /* Assuming no sane program has millions of iovs */
636 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000637 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200638 fprintf(stderr, "Out of memory\n");
639 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000640 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000641 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000642 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000643 /* include the buffer number to make it easy to
644 * match up the trace with the source */
645 tprintf(" * %lu bytes in buffer %d\n",
646 (unsigned long)iov_iov_len(i), i);
647 dumpstr(tcp, (long) iov_iov_base(i),
648 iov_iov_len(i));
649 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000650 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200651 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000652#undef sizeof_iov
653#undef iov_iov_base
654#undef iov_iov_len
655#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000656}
657#endif
658
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000659void
Denys Vlasenko12014262011-05-30 14:00:14 +0200660dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000661{
662 static int strsize = -1;
663 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000664
Denys Vlasenko76325802013-02-22 14:47:39 +0100665 char outbuf[
666 (
667 (sizeof(
668 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
669 "1234567890123456") + /*in case I'm off by few:*/ 4)
670 /*align to 8 to make memset easier:*/ + 7) & -8
671 ];
672 const unsigned char *src;
673 int i;
674
675 memset(outbuf, ' ', sizeof(outbuf));
676
677 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200678 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100679 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200680 if (!str) {
681 strsize = -1;
682 fprintf(stderr, "Out of memory\n");
683 return;
684 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100685 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 }
687
688 if (umoven(tcp, addr, len, (char *) str) < 0)
689 return;
690
Denys Vlasenko76325802013-02-22 14:47:39 +0100691 /* Space-pad to 16 bytes */
692 i = len;
693 while (i & 0xf)
694 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200695
Denys Vlasenko76325802013-02-22 14:47:39 +0100696 i = 0;
697 src = str;
698 while (i < len) {
699 char *dst = outbuf;
700 /* Hex dump */
701 do {
702 if (i < len) {
703 *dst++ = "0123456789abcdef"[*src >> 4];
704 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 }
706 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100707 *dst++ = ' ';
708 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100710 dst++; /* space is there by memset */
711 i++;
712 if ((i & 7) == 0)
713 dst++; /* space is there by memset */
714 src++;
715 } while (i & 0xf);
716 /* ASCII dump */
717 i -= 16;
718 src -= 16;
719 do {
720 if (*src >= ' ' && *src < 0x7f)
721 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100723 *dst++ = '.';
724 src++;
725 } while (++i & 0xf);
726 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100727 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 }
729}
730
Mike Frysinger612659e2012-02-14 14:38:28 +0100731#ifdef HAVE_PROCESS_VM_READV
732/* C library supports this, but the kernel might not. */
733static bool process_vm_readv_not_supported = 0;
734#else
735
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100736/* Need to do this since process_vm_readv() is not yet available in libc.
737 * When libc is be updated, only "static bool process_vm_readv_not_supported"
738 * line should remain.
739 */
740#if !defined(__NR_process_vm_readv)
741# if defined(I386)
742# define __NR_process_vm_readv 347
743# elif defined(X86_64)
744# define __NR_process_vm_readv 310
745# elif defined(POWERPC)
746# define __NR_process_vm_readv 351
747# endif
748#endif
749
750#if defined(__NR_process_vm_readv)
751static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400752/* Have to avoid duplicating with the C library headers. */
753static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100754 const struct iovec *lvec,
755 unsigned long liovcnt,
756 const struct iovec *rvec,
757 unsigned long riovcnt,
758 unsigned long flags)
759{
760 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
761}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400762#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100763#else
764static bool process_vm_readv_not_supported = 1;
765# define process_vm_readv(...) (errno = ENOSYS, -1)
766#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100767
768#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100769
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000770#define PAGMASK (~(PAGSIZ - 1))
771/*
772 * move `len' bytes of data from process `pid'
773 * at address `addr' to our space at `laddr'
774 */
775int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000776umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700778 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000779 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 union {
781 long val;
782 char x[sizeof(long)];
783 } u;
784
Denys Vlasenko2544f982013-02-19 17:39:56 +0100785#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100786 if (current_wordsize < sizeof(addr))
787 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100788#endif
789
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100790 if (!process_vm_readv_not_supported) {
791 struct iovec local[1], remote[1];
792 int r;
793
794 local[0].iov_base = laddr;
795 remote[0].iov_base = (void*)addr;
796 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000797 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100798 if (r == len)
799 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000800 if (r >= 0) {
801 error_msg("umoven: short read (%d < %d) @0x%lx",
802 r, len, addr);
803 return -1;
804 }
805 switch (errno) {
806 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100807 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000808 break;
809 case ESRCH:
810 /* the process is gone */
811 return -1;
812 case EFAULT: case EIO: case EPERM:
813 /* address space is inaccessible */
814 return -1;
815 default:
816 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100817 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000818 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100819 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100820 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100821
Dmitry V. Levin97005922013-02-26 21:16:22 +0000822 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000823 if (addr & (sizeof(long) - 1)) {
824 /* addr not a multiple of sizeof(long) */
825 n = addr - (addr & -sizeof(long)); /* residue */
826 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700827 errno = 0;
828 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000829 switch (errno) {
830 case 0:
831 break;
832 case ESRCH: case EINVAL:
833 /* these could be seen if the process is gone */
834 return -1;
835 case EFAULT: case EIO: case EPERM:
836 /* address space is inaccessible */
837 return -1;
838 default:
839 /* all the rest is strange and should be reported */
840 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
841 pid, addr);
842 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700843 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100844 m = MIN(sizeof(long) - n, len);
845 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100846 addr += sizeof(long);
847 laddr += m;
848 nread += m;
849 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 }
851 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700852 errno = 0;
853 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000854 switch (errno) {
855 case 0:
856 break;
857 case ESRCH: case EINVAL:
858 /* these could be seen if the process is gone */
859 return -1;
860 case EFAULT: case EIO: case EPERM:
861 /* address space is inaccessible */
862 if (nread) {
863 perror_msg("umoven: short read (%d < %d) @0x%lx",
864 nread, nread + len, addr - nread);
865 }
866 return -1;
867 default:
868 /* all the rest is strange and should be reported */
869 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
870 pid, addr);
871 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700872 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100873 m = MIN(sizeof(long), len);
874 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100875 addr += sizeof(long);
876 laddr += m;
877 nread += m;
878 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 return 0;
882}
883
884/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100885 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100887 *
888 * Returns < 0 on error, > 0 if NUL was seen,
889 * (TODO if useful: return count of bytes including NUL),
890 * else 0 if len bytes were read but no NUL byte seen.
891 *
892 * Note: there is no guarantee we won't overwrite some bytes
893 * in laddr[] _after_ terminating NUL (but, of course,
894 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 */
896int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000897umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898{
Denys Vlasenko16940922013-03-01 18:52:59 +0100899#if SIZEOF_LONG == 4
900 const unsigned long x01010101 = 0x01010101ul;
901 const unsigned long x80808080 = 0x80808080ul;
902#elif SIZEOF_LONG == 8
903 const unsigned long x01010101 = 0x0101010101010101ul;
904 const unsigned long x80808080 = 0x8080808080808080ul;
905#else
906# error SIZEOF_LONG > 8
907#endif
908
Roland McGratheb9e2e82009-06-02 16:49:22 -0700909 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100910 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100912 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 char x[sizeof(long)];
914 } u;
915
Denys Vlasenko2544f982013-02-19 17:39:56 +0100916#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100917 if (current_wordsize < sizeof(addr))
918 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000919#endif
920
Dmitry V. Levin97005922013-02-26 21:16:22 +0000921 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100922 if (!process_vm_readv_not_supported) {
923 struct iovec local[1], remote[1];
924
925 local[0].iov_base = laddr;
926 remote[0].iov_base = (void*)addr;
927
928 while (len > 0) {
929 int end_in_page;
930 int r;
931 int chunk_len;
932
933 /* Don't read kilobytes: most strings are short */
934 chunk_len = len;
935 if (chunk_len > 256)
936 chunk_len = 256;
937 /* Don't cross pages. I guess otherwise we can get EFAULT
938 * and fail to notice that terminating NUL lies
939 * in the existing (first) page.
940 * (I hope there aren't arches with pages < 4K)
941 */
942 end_in_page = ((addr + chunk_len) & 4095);
943 r = chunk_len - end_in_page;
944 if (r > 0) /* if chunk_len > end_in_page */
945 chunk_len = r; /* chunk_len -= end_in_page */
946
947 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000948 r = process_vm_readv(pid, local, 1, remote, 1, 0);
949 if (r > 0) {
950 if (memchr(local[0].iov_base, '\0', r))
951 return 1;
952 local[0].iov_base += r;
953 remote[0].iov_base += r;
954 len -= r;
955 nread += r;
956 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100957 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000958 switch (errno) {
959 case ENOSYS:
960 process_vm_readv_not_supported = 1;
961 goto vm_readv_didnt_work;
962 case ESRCH:
963 /* the process is gone */
964 return -1;
965 case EFAULT: case EIO: case EPERM:
966 /* address space is inaccessible */
967 if (nread) {
968 perror_msg("umovestr: short read (%d < %d) @0x%lx",
969 nread, nread + len, addr);
970 }
971 return -1;
972 default:
973 /* all the rest is strange and should be reported */
974 perror_msg("process_vm_readv");
975 return -1;
976 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100977 }
978 return 0;
979 }
980 vm_readv_didnt_work:
981
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982 if (addr & (sizeof(long) - 1)) {
983 /* addr not a multiple of sizeof(long) */
984 n = addr - (addr & -sizeof(long)); /* residue */
985 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700986 errno = 0;
987 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000988 switch (errno) {
989 case 0:
990 break;
991 case ESRCH: case EINVAL:
992 /* these could be seen if the process is gone */
993 return -1;
994 case EFAULT: case EIO: case EPERM:
995 /* address space is inaccessible */
996 return -1;
997 default:
998 /* all the rest is strange and should be reported */
999 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1000 pid, addr);
1001 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001002 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001003 m = MIN(sizeof(long) - n, len);
1004 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 while (n & (sizeof(long) - 1))
1006 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001007 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001008 addr += sizeof(long);
1009 laddr += m;
1010 nread += m;
1011 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001013
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001015 errno = 0;
1016 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001017 switch (errno) {
1018 case 0:
1019 break;
1020 case ESRCH: case EINVAL:
1021 /* these could be seen if the process is gone */
1022 return -1;
1023 case EFAULT: case EIO: case EPERM:
1024 /* address space is inaccessible */
1025 if (nread) {
1026 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1027 nread, nread + len, addr - nread);
1028 }
1029 return -1;
1030 default:
1031 /* all the rest is strange and should be reported */
1032 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1033 pid, addr);
1034 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001035 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001036 m = MIN(sizeof(long), len);
1037 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001038 /* "If a NUL char exists in this word" */
1039 if ((u.val - x01010101) & ~u.val & x80808080)
1040 return 1;
1041 addr += sizeof(long);
1042 laddr += m;
1043 nread += m;
1044 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001046 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047}
1048
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049int
Denys Vlasenko12014262011-05-30 14:00:14 +02001050upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051{
1052 long val;
1053
Roland McGratheb9e2e82009-06-02 16:49:22 -07001054 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +01001055 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001056 if (val == -1 && errno) {
1057 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001058 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001059 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001061 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 *res = val;
1063 return 0;
1064}
1065
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001066/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1067 * and PTRACE_O_TRACE[V]FORK for tracing children.
1068 * If you are adding a new arch which is only supported by newer kernels,
1069 * you most likely don't need to add any code below
1070 * beside a dummy "return 0" block in change_syscall().
1071 */
1072
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001073/*
1074 * These #if's are huge, please indent them correctly.
1075 * It's easy to get confused otherwise.
1076 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001078#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001079
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001080#ifndef CLONE_PTRACE
1081# define CLONE_PTRACE 0x00002000
1082#endif
1083#ifndef CLONE_VFORK
1084# define CLONE_VFORK 0x00004000
1085#endif
1086#ifndef CLONE_VM
1087# define CLONE_VM 0x00000100
1088#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001089
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001090#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001091
1092typedef unsigned long *arg_setup_state;
1093
1094static int
1095arg_setup(struct tcb *tcp, arg_setup_state *state)
1096{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001097 unsigned long cfm, sof, sol;
1098 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001099
Jan Kratochvil1f942712008-08-06 21:38:52 +00001100 if (ia32) {
1101 /* Satisfy a false GCC warning. */
1102 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001103 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001104 }
Roland McGrath08267b82004-02-20 22:56:43 +00001105
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001106 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001107 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001108 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001109 return -1;
1110
1111 sof = (cfm >> 0) & 0x7f;
1112 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001113 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001114
Jan Kratochvil1f942712008-08-06 21:38:52 +00001115 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001116 return 0;
1117}
1118
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001119# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001120
Roland McGrathd81f1d92003-01-09 06:53:34 +00001121static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001122get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001123{
Roland McGrath08267b82004-02-20 22:56:43 +00001124 int ret;
1125
1126 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001127 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001128 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001129 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001130 (unsigned long) ia64_rse_skip_regs(*state, 0),
1131 sizeof(long), (void *) valp);
1132 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001133}
1134
1135static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001136get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001137{
Roland McGrath08267b82004-02-20 22:56:43 +00001138 int ret;
1139
1140 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001141 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001142 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001143 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001144 (unsigned long) ia64_rse_skip_regs(*state, 1),
1145 sizeof(long), (void *) valp);
1146 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001147}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001148
1149static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001150set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001151{
Roland McGrath08267b82004-02-20 22:56:43 +00001152 int req = PTRACE_POKEDATA;
1153 void *ap;
1154
1155 if (ia32) {
1156 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1157 req = PTRACE_POKEUSER;
1158 } else
1159 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001160 errno = 0;
1161 ptrace(req, tcp->pid, ap, val);
1162 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001163}
1164
1165static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001166set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001167{
Roland McGrath08267b82004-02-20 22:56:43 +00001168 int req = PTRACE_POKEDATA;
1169 void *ap;
1170
1171 if (ia32) {
1172 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1173 req = PTRACE_POKEUSER;
1174 } else
1175 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001176 errno = 0;
1177 ptrace(req, tcp->pid, ap, val);
1178 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001179}
1180
Roland McGrathb659f872008-07-18 01:19:36 +00001181/* ia64 does not return the input arguments from functions (and syscalls)
1182 according to ia64 RSE (Register Stack Engine) behavior. */
1183
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001184# define restore_arg0(tcp, state, val) ((void) (state), 0)
1185# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001186
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001187#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001188
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001189# if defined(SPARC64)
1190# undef PTRACE_GETREGS
1191# define PTRACE_GETREGS PTRACE_GETREGS64
1192# undef PTRACE_SETREGS
1193# define PTRACE_SETREGS PTRACE_SETREGS64
1194# endif
1195
Mike Frysinger8566c502009-10-12 11:05:14 -04001196typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001197
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001198# define arg_setup(tcp, state) \
1199 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1200# define arg_finish_change(tcp, state) \
1201 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001203# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1204# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1205# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1206# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1207# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001208
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001209#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001211# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001212/* Note: this is only true for the `clone' system call, which handles
1213 arguments specially. We could as well say that its first two arguments
1214 are swapped relative to other architectures, but that would just be
1215 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001216# define arg0_offset PT_GPR3
1217# define arg1_offset PT_ORIGGPR2
1218# define restore_arg0(tcp, state, val) ((void) (state), 0)
1219# define restore_arg1(tcp, state, val) ((void) (state), 0)
1220# define arg0_index 1
1221# define arg1_index 0
1222# elif defined(ALPHA) || defined(MIPS)
1223# define arg0_offset REG_A0
1224# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001225# elif defined(POWERPC)
1226# define arg0_offset (sizeof(unsigned long)*PT_R3)
1227# define arg1_offset (sizeof(unsigned long)*PT_R4)
1228# define restore_arg0(tcp, state, val) ((void) (state), 0)
1229# elif defined(HPPA)
1230# define arg0_offset PT_GR26
1231# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001232# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001233# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1234# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1235# elif defined(SH)
1236# define arg0_offset (4*(REG_REG0+4))
1237# define arg1_offset (4*(REG_REG0+5))
1238# elif defined(SH64)
1239 /* ABI defines arg0 & 1 in r2 & r3 */
1240# define arg0_offset (REG_OFFSET+16)
1241# define arg1_offset (REG_OFFSET+24)
1242# define restore_arg0(tcp, state, val) 0
1243# elif defined CRISV10 || defined CRISV32
1244# define arg0_offset (4*PT_R11)
1245# define arg1_offset (4*PT_ORIG_R10)
1246# define restore_arg0(tcp, state, val) 0
1247# define restore_arg1(tcp, state, val) 0
1248# define arg0_index 1
1249# define arg1_index 0
1250# else
1251# define arg0_offset 0
1252# define arg1_offset 4
1253# if defined ARM
1254# define restore_arg0(tcp, state, val) 0
1255# endif
1256# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257
1258typedef int arg_setup_state;
1259
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001260# define arg_setup(tcp, state) (0)
1261# define arg_finish_change(tcp, state) 0
1262# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1263# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001264
1265static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001266set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001267{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001268 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269}
1270
1271static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001272set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001274 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275}
1276
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001277#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001278
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001279#ifndef restore_arg0
1280# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1281#endif
1282#ifndef restore_arg1
1283# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1284#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001285
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001286#ifndef arg0_index
1287# define arg0_index 0
1288# define arg1_index 1
1289#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001290
James Hogan05eb9052012-11-29 17:37:37 +00001291static int
1292change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1293{
1294#if defined(I386)
1295 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1296 return -1;
1297 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001298#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001299 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1300 return -1;
1301 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001302#elif defined(X32)
1303 /* setbpt/clearbpt never used: */
1304 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001305#elif defined(POWERPC)
1306 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1307 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1308 return -1;
1309 return 0;
1310#elif defined(S390) || defined(S390X)
1311 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1312 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1313 return -1;
1314 return 0;
1315#elif defined(M68K)
1316 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1317 return -1;
1318 return 0;
1319#elif defined(SPARC) || defined(SPARC64)
1320 state->u_regs[U_REG_G1] = new;
1321 return 0;
1322#elif defined(MIPS)
1323 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1324 return -1;
1325 return 0;
1326#elif defined(ALPHA)
1327 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1328 return -1;
1329 return 0;
1330#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001331 /* setbpt/clearbpt never used: */
1332 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001333#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001334 /* setbpt/clearbpt never used: */
1335 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001336#elif defined(IA64)
1337 if (ia32) {
1338 switch (new) {
1339 case 2:
1340 break; /* x86 SYS_fork */
1341 case SYS_clone:
1342 new = 120;
1343 break;
1344 default:
1345 fprintf(stderr, "%s: unexpected syscall %d\n",
1346 __FUNCTION__, new);
1347 return -1;
1348 }
1349 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1350 return -1;
1351 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1352 return -1;
1353 return 0;
1354#elif defined(HPPA)
1355 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1356 return -1;
1357 return 0;
1358#elif defined(SH)
1359 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1360 return -1;
1361 return 0;
1362#elif defined(SH64)
1363 /* Top half of reg encodes the no. of args n as 0x1n.
1364 Assume 0 args as kernel never actually checks... */
1365 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1366 0x100000 | new) < 0)
1367 return -1;
1368 return 0;
1369#elif defined(CRISV10) || defined(CRISV32)
1370 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1371 return -1;
1372 return 0;
1373#elif defined(ARM)
1374 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1375# ifndef PTRACE_SET_SYSCALL
1376# define PTRACE_SET_SYSCALL 23
1377# endif
1378 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1379 return -1;
1380 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001381#elif defined(AARCH64)
1382 /* setbpt/clearbpt never used: */
1383 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001384#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001385 /* setbpt/clearbpt never used: */
1386 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001387#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001388 /* setbpt/clearbpt never used: */
1389 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001390#elif defined(OR1K)
1391 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001392#elif defined(METAG)
1393 /* setbpt/clearbpt never used: */
1394 /* Meta is only supported since linux-3.7 */
James Hogan05eb9052012-11-29 17:37:37 +00001395#else
1396#warning Do not know how to handle change_syscall for this architecture
1397#endif /* architecture */
1398 return -1;
1399}
1400
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001402setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001403{
Roland McGrath3291ef22008-05-20 00:34:34 +00001404 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001405 arg_setup_state state;
1406
1407 if (tcp->flags & TCB_BPTSET) {
1408 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1409 return -1;
1410 }
1411
Roland McGrath3291ef22008-05-20 00:34:34 +00001412 /*
1413 * It's a silly kludge to initialize this with a search at runtime.
1414 * But it's better than maintaining another magic thing in the
1415 * godforsaken tables.
1416 */
1417 if (clone_scno[current_personality] == 0) {
1418 int i;
1419 for (i = 0; i < nsyscalls; ++i)
1420 if (sysent[i].sys_func == sys_clone) {
1421 clone_scno[current_personality] = i;
1422 break;
1423 }
1424 }
1425
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001426 if (tcp->s_ent->sys_func == sys_fork ||
1427 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001428 if (arg_setup(tcp, &state) < 0
1429 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1430 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001431 || change_syscall(tcp, &state,
1432 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001433 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1434 || set_arg1(tcp, &state, 0) < 0
1435 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001436 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001437 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1438 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001439 tcp->flags |= TCB_BPTSET;
1440 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001441 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001442
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001443 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001444 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001445 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001446 vfork semantics into plain fork - each application must not
1447 depend on the vfork specifics according to POSIX. We would
1448 hang waiting for the parent resume otherwise. We need to
1449 clear also CLONE_VM but only in the CLONE_VFORK case as
1450 otherwise we would break pthread_create. */
1451
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001452 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1453 if (new_arg0 & CLONE_VFORK)
1454 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1455 if (arg_setup(tcp, &state) < 0
1456 || set_arg0(tcp, &state, new_arg0) < 0
1457 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001458 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001459 tcp->inst[0] = tcp->u_arg[arg0_index];
1460 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001461 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001463 }
1464
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001465 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1466 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001467 return -1;
1468}
1469
1470int
Denys Vlasenko12014262011-05-30 14:00:14 +02001471clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001472{
1473 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001474 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001475 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001476 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1477 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1478 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001479 if (errno != ESRCH)
1480 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481 tcp->flags &= ~TCB_BPTSET;
1482 return 0;
1483}