blob: 83fdf293a14793544b023fb7d721b618acff23fa [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 +000063int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000064string_to_uint(const char *str)
65{
66 char *error;
67 long value;
68
69 if (!*str)
70 return -1;
71 errno = 0;
72 value = strtol(str, &error, 10);
73 if (errno || *error || value < 0 || (long)(int)value != value)
74 return -1;
75 return (int)value;
76}
77
78int
Denys Vlasenko12014262011-05-30 14:00:14 +020079tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080{
81 return a->tv_sec || a->tv_usec;
82}
83
84int
Denys Vlasenko12014262011-05-30 14:00:14 +020085tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086{
87 if (a->tv_sec < b->tv_sec
88 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
89 return -1;
90 if (a->tv_sec > b->tv_sec
91 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
92 return 1;
93 return 0;
94}
95
96double
Denys Vlasenko12014262011-05-30 14:00:14 +020097tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098{
99 return tv->tv_sec + tv->tv_usec/1000000.0;
100}
101
102void
Denys Vlasenko12014262011-05-30 14:00:14 +0200103tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104{
105 tv->tv_sec = a->tv_sec + b->tv_sec;
106 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000107 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108 tv->tv_sec++;
109 tv->tv_usec -= 1000000;
110 }
111}
112
113void
Denys Vlasenko12014262011-05-30 14:00:14 +0200114tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115{
116 tv->tv_sec = a->tv_sec - b->tv_sec;
117 tv->tv_usec = a->tv_usec - b->tv_usec;
118 if (((long) tv->tv_usec) < 0) {
119 tv->tv_sec--;
120 tv->tv_usec += 1000000;
121 }
122}
123
124void
Denys Vlasenko12014262011-05-30 14:00:14 +0200125tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126{
127 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
128 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
129 tv->tv_usec %= 1000000;
130}
131
132void
Denys Vlasenko12014262011-05-30 14:00:14 +0200133tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134{
135 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000136 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137 tv->tv_usec %= 1000000;
138}
139
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000140const char *
141xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142{
143 for (; xlat->str != NULL; xlat++)
144 if (xlat->val == val)
145 return xlat->str;
146 return NULL;
147}
148
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200149#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200150char *
151stpcpy(char *dst, const char *src)
152{
153 while ((*dst = *src++) != '\0')
154 dst++;
155 return dst;
156}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200157#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200158
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159/*
160 * Print entry in struct xlat table, if there.
161 */
162void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000163printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000165 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166
167 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200168 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169 else
170 tprintf("%#x /* %s */", val, dflt);
171}
172
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100173/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100174 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100175 * argument.
176 */
177int
Chris Metcalf879dddd2013-03-01 10:41:02 +0100178printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100179{
Mike Frysinger921744d2013-05-04 01:42:54 -0400180#if defined(X86_64) || defined(POWERPC64) || defined(TILE) || defined(AARCH64) || \
Mike Frysinger80acf622013-05-04 13:25:22 -0400181 defined(LINUX_MIPSN64) || defined(SPARC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100182 if (current_personality == 0) {
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100183 /* Technically, format expects "long long",
184 * but we supply "long". We expect that
185 * on this arch, they are the same.
186 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100187 tprintf(format, tcp->u_arg[arg_no]);
188 arg_no++;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100189 } else {
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000190# if defined(AARCH64) || defined(POWERPC64)
191 /* Align arg_no to the next even number. */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100192 arg_no = (arg_no + 1) & 0xe;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100193# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100194 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
195 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100196 }
Mike Frysinger6303f352013-04-30 23:48:07 -0400197#elif defined IA64 || defined ALPHA || defined S390X
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100198 /* Technically, format expects "long long",
199 * but we supply "long". We expect that
200 * on this arch, they are the same.
201 */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100202 tprintf(format, tcp->u_arg[arg_no]);
203 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000204#elif defined X32
205 if (current_personality == 0) {
206 tprintf(format, tcp->ext_arg[arg_no]);
207 arg_no++;
208 } else {
209 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
210 arg_no += 2;
211 }
212#elif defined LINUX_MIPSN32
Chris Metcalf879dddd2013-03-01 10:41:02 +0100213 tprintf(format, tcp->ext_arg[arg_no]);
214 arg_no++;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100215#else
216# if SIZEOF_LONG > 4
217# error BUG: must not combine two args for long long on this arch
218# endif
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000219#if defined(ARM) || defined(POWERPC)
220 /* Align arg_no to the next even number. */
221 arg_no = (arg_no + 1) & 0xe;
222#endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100223 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
224 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100225#endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100226 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100227}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100228
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229/*
230 * Interpret `xlat' as an array of flags
231 * print the entries whose bits are on in `flags'
232 * return # of flags printed.
233 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200234void
Denys Vlasenko12014262011-05-30 14:00:14 +0200235addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200237 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238 if (xlat->val && (flags & xlat->val) == xlat->val) {
239 tprintf("|%s", xlat->str);
240 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241 }
242 }
243 if (flags) {
244 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000245 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246}
247
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000248/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200249 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000250 * Print to static string the entries whose bits are on in `flags'
251 * Return static string.
252 */
253const char *
254sprintflags(const char *prefix, const struct xlat *xlat, int flags)
255{
256 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200257 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000258 int found = 0;
259
Denys Vlasenko52845572011-08-31 12:07:38 +0200260 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000261
262 for (; xlat->str; xlat++) {
263 if ((flags & xlat->val) == xlat->val) {
264 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200265 *outptr++ = '|';
266 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000267 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100268 flags &= ~xlat->val;
269 if (!flags)
270 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000271 }
272 }
273 if (flags) {
274 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200275 *outptr++ = '|';
276 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000277 }
278
279 return outstr;
280}
281
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000283printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284{
285 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000286 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287
288 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200289 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290 return 1;
291 }
292
293 sep = "";
294 for (n = 0; xlat->str; xlat++) {
295 if (xlat->val && (flags & xlat->val) == xlat->val) {
296 tprintf("%s%s", sep, xlat->str);
297 flags &= ~xlat->val;
298 sep = "|";
299 n++;
300 }
301 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000302
303 if (n) {
304 if (flags) {
305 tprintf("%s%#x", sep, flags);
306 n++;
307 }
308 } else {
309 if (flags) {
310 tprintf("%#x", flags);
311 if (dflt)
312 tprintf(" /* %s */", dflt);
313 } else {
314 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200315 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000316 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000318
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319 return n;
320}
321
322void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000323printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324{
Roland McGratheb285352003-01-14 09:59:00 +0000325 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326
327 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200328 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000329 return;
330 }
331 if (umove(tcp, addr, &num) < 0) {
332 tprintf("%#lx", addr);
333 return;
334 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200335 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200337 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338}
339
Roland McGrath6bc12202003-11-13 22:32:27 +0000340void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000341printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000342{
343 int num;
344
345 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200346 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000347 return;
348 }
349 if (umove(tcp, addr, &num) < 0) {
350 tprintf("%#lx", addr);
351 return;
352 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200353 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000354 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200355 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000356}
357
358void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300359printfd(struct tcb *tcp, int fd)
360{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100361 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000362
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100363 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
364 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000365 else
366 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300367}
368
369void
Denys Vlasenko12014262011-05-30 14:00:14 +0200370printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000371{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200372 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000373}
374
Dmitry V. Levina501f142008-11-10 23:19:13 +0000375/*
376 * Quote string `instr' of length `size'
377 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200378 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000379 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100380 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200381 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100382 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000383 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400384int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200385string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000386{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000387 const unsigned char *ustr = (const unsigned char *) instr;
388 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200389 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200391 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200392 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200393 size--;
394 eol = '\0';
395 }
396
397 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000398 if (xflag > 1)
399 usehex = 1;
400 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000401 /* Check for presence of symbol which require
402 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000403 for (i = 0; i < size; ++i) {
404 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000405 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200406 if (c == eol)
407 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100408
409 /* Force hex unless c is printable or whitespace */
410 if (c > 0x7e) {
411 usehex = 1;
412 break;
413 }
414 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
415 * They happen to have ASCII codes 9,10,11,12,13.
416 */
417 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000418 usehex = 1;
419 break;
420 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000421 }
422 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423
424 *s++ = '\"';
425
426 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000427 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000428 for (i = 0; i < size; ++i) {
429 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000430 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200431 if (c == eol)
432 goto asciz_ended;
433 *s++ = '\\';
434 *s++ = 'x';
435 *s++ = "0123456789abcdef"[c >> 4];
436 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000437 }
438 } else {
439 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;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000444 switch (c) {
445 case '\"': case '\\':
446 *s++ = '\\';
447 *s++ = c;
448 break;
449 case '\f':
450 *s++ = '\\';
451 *s++ = 'f';
452 break;
453 case '\n':
454 *s++ = '\\';
455 *s++ = 'n';
456 break;
457 case '\r':
458 *s++ = '\\';
459 *s++ = 'r';
460 break;
461 case '\t':
462 *s++ = '\\';
463 *s++ = 't';
464 break;
465 case '\v':
466 *s++ = '\\';
467 *s++ = 'v';
468 break;
469 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100470 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000471 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200472 else {
473 /* Print \octal */
474 *s++ = '\\';
475 if (i + 1 < size
476 && ustr[i + 1] >= '0'
477 && ustr[i + 1] <= '9'
478 ) {
479 /* Print \ooo */
480 *s++ = '0' + (c >> 6);
481 *s++ = '0' + ((c >> 3) & 0x7);
482 } else {
483 /* Print \[[o]o]o */
484 if ((c >> 3) != 0) {
485 if ((c >> 6) != 0)
486 *s++ = '0' + (c >> 6);
487 *s++ = '0' + ((c >> 3) & 0x7);
488 }
489 }
490 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000491 }
492 break;
493 }
494 }
495 }
496
497 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000499
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200500 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200501 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200502 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
503 * but next char is NUL.
504 */
505 return 0;
506 }
507
508 return 1;
509
510 asciz_ended:
511 *s++ = '\"';
512 *s = '\0';
513 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
514 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515}
516
Dmitry V. Levina501f142008-11-10 23:19:13 +0000517/*
518 * Print path string specified by address `addr' and length `n'.
519 * If path length exceeds `n', append `...' to the output.
520 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000522printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100524 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100525 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100526
Dmitry V. Levina501f142008-11-10 23:19:13 +0000527 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200528 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000529 return;
530 }
531
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100532 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000533 if (n > sizeof path - 1)
534 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000535
536 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100537 nul_seen = umovestr(tcp, addr, n + 1, path);
538 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 tprintf("%#lx", addr);
540 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100541 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000542
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100543 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100544 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100545 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100546 string_quote(path, outstr, -1, n);
547 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100548 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100549 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550 }
551}
552
553void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000554printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100556 /* Size must correspond to char path[] size in printpathn */
557 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000558}
559
Dmitry V. Levina501f142008-11-10 23:19:13 +0000560/*
561 * Print string specified by address `addr' and length `len'.
562 * If `len' < 0, treat the string as a NUL-terminated string.
563 * If string length exceeds `max_strlen', append `...' to the output.
564 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200566printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567{
568 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000570 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100571 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572
573 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200574 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 return;
576 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000577 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200578 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000579 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
580
581 if (outstr_size / 4 != max_strlen)
582 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000583 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200584 if (!str)
585 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000586 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200587 if (!outstr)
588 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000589 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000590
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200591 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000592 /*
593 * Treat as a NUL-terminated string: fetch one byte more
594 * because string_quote() quotes one byte less.
595 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000596 size = max_strlen + 1;
597 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 tprintf("%#lx", addr);
599 return;
600 }
601 }
602 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200603 size = max_strlen;
604 if (size > (unsigned long)len)
605 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000606 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 tprintf("%#lx", addr);
608 return;
609 }
610 }
611
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100612 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
613 * or we were requested to print more than -s NUM chars)...
614 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100615 ellipsis = (string_quote(str, outstr, len, size) &&
616 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000617
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100618 tprints(outstr);
619 if (ellipsis)
620 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000621}
622
John Hughes1d08dcf2001-07-10 13:48:44 +0000623#if HAVE_SYS_UIO_H
624void
Denys Vlasenko12014262011-05-30 14:00:14 +0200625dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000626{
Denys Vlasenko84703742012-02-25 02:38:52 +0100627#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000628 union {
629 struct { u_int32_t base; u_int32_t len; } *iov32;
630 struct { u_int64_t base; u_int64_t len; } *iov64;
631 } iovu;
632#define iov iovu.iov64
633#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100634 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000635#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100636 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000637#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100638 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000639#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000640 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000641#define sizeof_iov sizeof(*iov)
642#define iov_iov_base(i) iov[i].iov_base
643#define iov_iov_len(i) iov[i].iov_len
644#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000645 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200646 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000647
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200648 size = sizeof_iov * len;
649 /* Assuming no sane program has millions of iovs */
650 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000651 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200652 fprintf(stderr, "Out of memory\n");
653 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000654 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000655 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000656 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000657 /* include the buffer number to make it easy to
658 * match up the trace with the source */
659 tprintf(" * %lu bytes in buffer %d\n",
660 (unsigned long)iov_iov_len(i), i);
661 dumpstr(tcp, (long) iov_iov_base(i),
662 iov_iov_len(i));
663 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000664 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200665 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000666#undef sizeof_iov
667#undef iov_iov_base
668#undef iov_iov_len
669#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000670}
671#endif
672
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673void
Denys Vlasenko12014262011-05-30 14:00:14 +0200674dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675{
676 static int strsize = -1;
677 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678
Denys Vlasenko76325802013-02-22 14:47:39 +0100679 char outbuf[
680 (
681 (sizeof(
682 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
683 "1234567890123456") + /*in case I'm off by few:*/ 4)
684 /*align to 8 to make memset easier:*/ + 7) & -8
685 ];
686 const unsigned char *src;
687 int i;
688
689 memset(outbuf, ' ', sizeof(outbuf));
690
691 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200692 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100693 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200694 if (!str) {
695 strsize = -1;
696 fprintf(stderr, "Out of memory\n");
697 return;
698 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100699 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700 }
701
702 if (umoven(tcp, addr, len, (char *) str) < 0)
703 return;
704
Denys Vlasenko76325802013-02-22 14:47:39 +0100705 /* Space-pad to 16 bytes */
706 i = len;
707 while (i & 0xf)
708 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200709
Denys Vlasenko76325802013-02-22 14:47:39 +0100710 i = 0;
711 src = str;
712 while (i < len) {
713 char *dst = outbuf;
714 /* Hex dump */
715 do {
716 if (i < len) {
717 *dst++ = "0123456789abcdef"[*src >> 4];
718 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 }
720 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100721 *dst++ = ' ';
722 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100724 dst++; /* space is there by memset */
725 i++;
726 if ((i & 7) == 0)
727 dst++; /* space is there by memset */
728 src++;
729 } while (i & 0xf);
730 /* ASCII dump */
731 i -= 16;
732 src -= 16;
733 do {
734 if (*src >= ' ' && *src < 0x7f)
735 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000736 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100737 *dst++ = '.';
738 src++;
739 } while (++i & 0xf);
740 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100741 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 }
743}
744
Mike Frysinger612659e2012-02-14 14:38:28 +0100745#ifdef HAVE_PROCESS_VM_READV
746/* C library supports this, but the kernel might not. */
747static bool process_vm_readv_not_supported = 0;
748#else
749
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100750/* Need to do this since process_vm_readv() is not yet available in libc.
751 * When libc is be updated, only "static bool process_vm_readv_not_supported"
752 * line should remain.
753 */
754#if !defined(__NR_process_vm_readv)
755# if defined(I386)
756# define __NR_process_vm_readv 347
757# elif defined(X86_64)
758# define __NR_process_vm_readv 310
759# elif defined(POWERPC)
760# define __NR_process_vm_readv 351
761# endif
762#endif
763
764#if defined(__NR_process_vm_readv)
765static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400766/* Have to avoid duplicating with the C library headers. */
767static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100768 const struct iovec *lvec,
769 unsigned long liovcnt,
770 const struct iovec *rvec,
771 unsigned long riovcnt,
772 unsigned long flags)
773{
774 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
775}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400776#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100777#else
778static bool process_vm_readv_not_supported = 1;
779# define process_vm_readv(...) (errno = ENOSYS, -1)
780#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100781
782#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100783
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784#define PAGMASK (~(PAGSIZ - 1))
785/*
786 * move `len' bytes of data from process `pid'
787 * at address `addr' to our space at `laddr'
788 */
789int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000790umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700792 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000793 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 union {
795 long val;
796 char x[sizeof(long)];
797 } u;
798
Denys Vlasenko2544f982013-02-19 17:39:56 +0100799#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100800 if (current_wordsize < sizeof(addr))
801 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100802#endif
803
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100804 if (!process_vm_readv_not_supported) {
805 struct iovec local[1], remote[1];
806 int r;
807
808 local[0].iov_base = laddr;
809 remote[0].iov_base = (void*)addr;
810 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000811 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100812 if (r == len)
813 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000814 if (r >= 0) {
815 error_msg("umoven: short read (%d < %d) @0x%lx",
816 r, len, addr);
817 return -1;
818 }
819 switch (errno) {
820 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100821 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000822 break;
823 case ESRCH:
824 /* the process is gone */
825 return -1;
826 case EFAULT: case EIO: case EPERM:
827 /* address space is inaccessible */
828 return -1;
829 default:
830 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100831 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000832 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100833 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100834 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100835
Dmitry V. Levin97005922013-02-26 21:16:22 +0000836 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837 if (addr & (sizeof(long) - 1)) {
838 /* addr not a multiple of sizeof(long) */
839 n = addr - (addr & -sizeof(long)); /* residue */
840 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700841 errno = 0;
842 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000843 switch (errno) {
844 case 0:
845 break;
846 case ESRCH: case EINVAL:
847 /* these could be seen if the process is gone */
848 return -1;
849 case EFAULT: case EIO: case EPERM:
850 /* address space is inaccessible */
851 return -1;
852 default:
853 /* all the rest is strange and should be reported */
854 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
855 pid, addr);
856 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700857 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100858 m = MIN(sizeof(long) - n, len);
859 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100860 addr += sizeof(long);
861 laddr += m;
862 nread += m;
863 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 }
865 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700866 errno = 0;
867 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000868 switch (errno) {
869 case 0:
870 break;
871 case ESRCH: case EINVAL:
872 /* these could be seen if the process is gone */
873 return -1;
874 case EFAULT: case EIO: case EPERM:
875 /* address space is inaccessible */
876 if (nread) {
877 perror_msg("umoven: short read (%d < %d) @0x%lx",
878 nread, nread + len, addr - nread);
879 }
880 return -1;
881 default:
882 /* all the rest is strange and should be reported */
883 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
884 pid, addr);
885 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700886 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100887 m = MIN(sizeof(long), len);
888 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100889 addr += sizeof(long);
890 laddr += m;
891 nread += m;
892 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 return 0;
896}
897
898/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100899 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100901 *
902 * Returns < 0 on error, > 0 if NUL was seen,
903 * (TODO if useful: return count of bytes including NUL),
904 * else 0 if len bytes were read but no NUL byte seen.
905 *
906 * Note: there is no guarantee we won't overwrite some bytes
907 * in laddr[] _after_ terminating NUL (but, of course,
908 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 */
910int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000911umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912{
Denys Vlasenko16940922013-03-01 18:52:59 +0100913#if SIZEOF_LONG == 4
914 const unsigned long x01010101 = 0x01010101ul;
915 const unsigned long x80808080 = 0x80808080ul;
916#elif SIZEOF_LONG == 8
917 const unsigned long x01010101 = 0x0101010101010101ul;
918 const unsigned long x80808080 = 0x8080808080808080ul;
919#else
920# error SIZEOF_LONG > 8
921#endif
922
Roland McGratheb9e2e82009-06-02 16:49:22 -0700923 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100924 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100926 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 char x[sizeof(long)];
928 } u;
929
Denys Vlasenko2544f982013-02-19 17:39:56 +0100930#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100931 if (current_wordsize < sizeof(addr))
932 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000933#endif
934
Dmitry V. Levin97005922013-02-26 21:16:22 +0000935 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100936 if (!process_vm_readv_not_supported) {
937 struct iovec local[1], remote[1];
938
939 local[0].iov_base = laddr;
940 remote[0].iov_base = (void*)addr;
941
942 while (len > 0) {
943 int end_in_page;
944 int r;
945 int chunk_len;
946
947 /* Don't read kilobytes: most strings are short */
948 chunk_len = len;
949 if (chunk_len > 256)
950 chunk_len = 256;
951 /* Don't cross pages. I guess otherwise we can get EFAULT
952 * and fail to notice that terminating NUL lies
953 * in the existing (first) page.
954 * (I hope there aren't arches with pages < 4K)
955 */
956 end_in_page = ((addr + chunk_len) & 4095);
957 r = chunk_len - end_in_page;
958 if (r > 0) /* if chunk_len > end_in_page */
959 chunk_len = r; /* chunk_len -= end_in_page */
960
961 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000962 r = process_vm_readv(pid, local, 1, remote, 1, 0);
963 if (r > 0) {
964 if (memchr(local[0].iov_base, '\0', r))
965 return 1;
966 local[0].iov_base += r;
967 remote[0].iov_base += r;
968 len -= r;
969 nread += r;
970 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100971 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000972 switch (errno) {
973 case ENOSYS:
974 process_vm_readv_not_supported = 1;
975 goto vm_readv_didnt_work;
976 case ESRCH:
977 /* the process is gone */
978 return -1;
979 case EFAULT: case EIO: case EPERM:
980 /* address space is inaccessible */
981 if (nread) {
982 perror_msg("umovestr: short read (%d < %d) @0x%lx",
983 nread, nread + len, addr);
984 }
985 return -1;
986 default:
987 /* all the rest is strange and should be reported */
988 perror_msg("process_vm_readv");
989 return -1;
990 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100991 }
992 return 0;
993 }
994 vm_readv_didnt_work:
995
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 if (addr & (sizeof(long) - 1)) {
997 /* addr not a multiple of sizeof(long) */
998 n = addr - (addr & -sizeof(long)); /* residue */
999 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001000 errno = 0;
1001 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001002 switch (errno) {
1003 case 0:
1004 break;
1005 case ESRCH: case EINVAL:
1006 /* these could be seen if the process is gone */
1007 return -1;
1008 case EFAULT: case EIO: case EPERM:
1009 /* address space is inaccessible */
1010 return -1;
1011 default:
1012 /* all the rest is strange and should be reported */
1013 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1014 pid, addr);
1015 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001016 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001017 m = MIN(sizeof(long) - n, len);
1018 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 while (n & (sizeof(long) - 1))
1020 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001021 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001022 addr += sizeof(long);
1023 laddr += m;
1024 nread += m;
1025 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001027
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001029 errno = 0;
1030 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001031 switch (errno) {
1032 case 0:
1033 break;
1034 case ESRCH: case EINVAL:
1035 /* these could be seen if the process is gone */
1036 return -1;
1037 case EFAULT: case EIO: case EPERM:
1038 /* address space is inaccessible */
1039 if (nread) {
1040 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1041 nread, nread + len, addr - nread);
1042 }
1043 return -1;
1044 default:
1045 /* all the rest is strange and should be reported */
1046 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1047 pid, addr);
1048 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001049 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001050 m = MIN(sizeof(long), len);
1051 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001052 /* "If a NUL char exists in this word" */
1053 if ((u.val - x01010101) & ~u.val & x80808080)
1054 return 1;
1055 addr += sizeof(long);
1056 laddr += m;
1057 nread += m;
1058 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001060 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061}
1062
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063int
Denys Vlasenko12014262011-05-30 14:00:14 +02001064upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065{
1066 long val;
1067
Roland McGratheb9e2e82009-06-02 16:49:22 -07001068 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +01001069 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001070 if (val == -1 && errno) {
1071 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001072 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001073 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001075 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 *res = val;
1077 return 0;
1078}
1079
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001080/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1081 * and PTRACE_O_TRACE[V]FORK for tracing children.
1082 * If you are adding a new arch which is only supported by newer kernels,
1083 * you most likely don't need to add any code below
1084 * beside a dummy "return 0" block in change_syscall().
1085 */
1086
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001087/*
1088 * These #if's are huge, please indent them correctly.
1089 * It's easy to get confused otherwise.
1090 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001092#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001093
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001094#ifndef CLONE_PTRACE
1095# define CLONE_PTRACE 0x00002000
1096#endif
1097#ifndef CLONE_VFORK
1098# define CLONE_VFORK 0x00004000
1099#endif
1100#ifndef CLONE_VM
1101# define CLONE_VM 0x00000100
1102#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001103
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001104#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001105
1106typedef unsigned long *arg_setup_state;
1107
1108static int
1109arg_setup(struct tcb *tcp, arg_setup_state *state)
1110{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001111 unsigned long cfm, sof, sol;
1112 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001113
Jan Kratochvil1f942712008-08-06 21:38:52 +00001114 if (ia32) {
1115 /* Satisfy a false GCC warning. */
1116 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001117 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001118 }
Roland McGrath08267b82004-02-20 22:56:43 +00001119
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001120 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001121 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001122 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001123 return -1;
1124
1125 sof = (cfm >> 0) & 0x7f;
1126 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001127 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001128
Jan Kratochvil1f942712008-08-06 21:38:52 +00001129 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001130 return 0;
1131}
1132
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001133# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001134
Roland McGrathd81f1d92003-01-09 06:53:34 +00001135static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001136get_arg0(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_R11, 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, 0),
1145 sizeof(long), (void *) valp);
1146 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001147}
1148
1149static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001150get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001151{
Roland McGrath08267b82004-02-20 22:56:43 +00001152 int ret;
1153
1154 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001155 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001156 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001157 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001158 (unsigned long) ia64_rse_skip_regs(*state, 1),
1159 sizeof(long), (void *) valp);
1160 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001161}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001162
1163static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001164set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001165{
Roland McGrath08267b82004-02-20 22:56:43 +00001166 int req = PTRACE_POKEDATA;
1167 void *ap;
1168
1169 if (ia32) {
1170 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1171 req = PTRACE_POKEUSER;
1172 } else
1173 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001174 errno = 0;
1175 ptrace(req, tcp->pid, ap, val);
1176 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001177}
1178
1179static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001180set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001181{
Roland McGrath08267b82004-02-20 22:56:43 +00001182 int req = PTRACE_POKEDATA;
1183 void *ap;
1184
1185 if (ia32) {
1186 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1187 req = PTRACE_POKEUSER;
1188 } else
1189 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001190 errno = 0;
1191 ptrace(req, tcp->pid, ap, val);
1192 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001193}
1194
Roland McGrathb659f872008-07-18 01:19:36 +00001195/* ia64 does not return the input arguments from functions (and syscalls)
1196 according to ia64 RSE (Register Stack Engine) behavior. */
1197
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001198# define restore_arg0(tcp, state, val) ((void) (state), 0)
1199# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001200
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001201#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001203# if defined(SPARC64)
1204# undef PTRACE_GETREGS
1205# define PTRACE_GETREGS PTRACE_GETREGS64
1206# undef PTRACE_SETREGS
1207# define PTRACE_SETREGS PTRACE_SETREGS64
1208# endif
1209
Mike Frysinger8566c502009-10-12 11:05:14 -04001210typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001212# define arg_setup(tcp, state) \
1213 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1214# define arg_finish_change(tcp, state) \
1215 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001216
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001217# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1218# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1219# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1220# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1221# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001222
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001223#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001224
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001225# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001226/* Note: this is only true for the `clone' system call, which handles
1227 arguments specially. We could as well say that its first two arguments
1228 are swapped relative to other architectures, but that would just be
1229 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001230# define arg0_offset PT_GPR3
1231# define arg1_offset PT_ORIGGPR2
1232# define restore_arg0(tcp, state, val) ((void) (state), 0)
1233# define restore_arg1(tcp, state, val) ((void) (state), 0)
1234# define arg0_index 1
1235# define arg1_index 0
1236# elif defined(ALPHA) || defined(MIPS)
1237# define arg0_offset REG_A0
1238# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001239# elif defined(POWERPC)
1240# define arg0_offset (sizeof(unsigned long)*PT_R3)
1241# define arg1_offset (sizeof(unsigned long)*PT_R4)
1242# define restore_arg0(tcp, state, val) ((void) (state), 0)
1243# elif defined(HPPA)
1244# define arg0_offset PT_GR26
1245# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001246# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001247# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1248# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1249# elif defined(SH)
1250# define arg0_offset (4*(REG_REG0+4))
1251# define arg1_offset (4*(REG_REG0+5))
1252# elif defined(SH64)
1253 /* ABI defines arg0 & 1 in r2 & r3 */
1254# define arg0_offset (REG_OFFSET+16)
1255# define arg1_offset (REG_OFFSET+24)
1256# define restore_arg0(tcp, state, val) 0
1257# elif defined CRISV10 || defined CRISV32
1258# define arg0_offset (4*PT_R11)
1259# define arg1_offset (4*PT_ORIG_R10)
1260# define restore_arg0(tcp, state, val) 0
1261# define restore_arg1(tcp, state, val) 0
1262# define arg0_index 1
1263# define arg1_index 0
1264# else
1265# define arg0_offset 0
1266# define arg1_offset 4
1267# if defined ARM
1268# define restore_arg0(tcp, state, val) 0
1269# endif
1270# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271
1272typedef int arg_setup_state;
1273
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001274# define arg_setup(tcp, state) (0)
1275# define arg_finish_change(tcp, state) 0
1276# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1277# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001278
1279static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001280set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001282 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283}
1284
1285static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001286set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001288 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001289}
1290
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001291#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001293#ifndef restore_arg0
1294# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1295#endif
1296#ifndef restore_arg1
1297# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1298#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001300#ifndef arg0_index
1301# define arg0_index 0
1302# define arg1_index 1
1303#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001304
James Hogan05eb9052012-11-29 17:37:37 +00001305static int
1306change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1307{
1308#if defined(I386)
1309 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1310 return -1;
1311 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001312#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001313 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1314 return -1;
1315 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001316#elif defined(X32)
1317 /* setbpt/clearbpt never used: */
1318 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001319#elif defined(POWERPC)
1320 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1321 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1322 return -1;
1323 return 0;
1324#elif defined(S390) || defined(S390X)
1325 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1326 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1327 return -1;
1328 return 0;
1329#elif defined(M68K)
1330 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1331 return -1;
1332 return 0;
1333#elif defined(SPARC) || defined(SPARC64)
1334 state->u_regs[U_REG_G1] = new;
1335 return 0;
1336#elif defined(MIPS)
1337 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1338 return -1;
1339 return 0;
1340#elif defined(ALPHA)
1341 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1342 return -1;
1343 return 0;
1344#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001345 /* setbpt/clearbpt never used: */
1346 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001347#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001348 /* setbpt/clearbpt never used: */
1349 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001350#elif defined(IA64)
1351 if (ia32) {
1352 switch (new) {
1353 case 2:
1354 break; /* x86 SYS_fork */
1355 case SYS_clone:
1356 new = 120;
1357 break;
1358 default:
1359 fprintf(stderr, "%s: unexpected syscall %d\n",
1360 __FUNCTION__, new);
1361 return -1;
1362 }
1363 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1364 return -1;
1365 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1366 return -1;
1367 return 0;
1368#elif defined(HPPA)
1369 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1370 return -1;
1371 return 0;
1372#elif defined(SH)
1373 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1374 return -1;
1375 return 0;
1376#elif defined(SH64)
1377 /* Top half of reg encodes the no. of args n as 0x1n.
1378 Assume 0 args as kernel never actually checks... */
1379 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1380 0x100000 | new) < 0)
1381 return -1;
1382 return 0;
1383#elif defined(CRISV10) || defined(CRISV32)
1384 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1385 return -1;
1386 return 0;
1387#elif defined(ARM)
1388 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1389# ifndef PTRACE_SET_SYSCALL
1390# define PTRACE_SET_SYSCALL 23
1391# endif
1392 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1393 return -1;
1394 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001395#elif defined(AARCH64)
1396 /* setbpt/clearbpt never used: */
1397 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001398#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001399 /* setbpt/clearbpt never used: */
1400 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001401#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001402 /* setbpt/clearbpt never used: */
1403 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001404#elif defined(OR1K)
1405 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001406#elif defined(METAG)
1407 /* setbpt/clearbpt never used: */
1408 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001409#elif defined(XTENSA)
1410 /* setbpt/clearbpt never used: */
1411 /* Xtensa is only supported since linux 2.6.13 */
James Hogan05eb9052012-11-29 17:37:37 +00001412#else
1413#warning Do not know how to handle change_syscall for this architecture
1414#endif /* architecture */
1415 return -1;
1416}
1417
Roland McGrathd81f1d92003-01-09 06:53:34 +00001418int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001419setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420{
Roland McGrath3291ef22008-05-20 00:34:34 +00001421 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422 arg_setup_state state;
1423
1424 if (tcp->flags & TCB_BPTSET) {
1425 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1426 return -1;
1427 }
1428
Roland McGrath3291ef22008-05-20 00:34:34 +00001429 /*
1430 * It's a silly kludge to initialize this with a search at runtime.
1431 * But it's better than maintaining another magic thing in the
1432 * godforsaken tables.
1433 */
1434 if (clone_scno[current_personality] == 0) {
1435 int i;
1436 for (i = 0; i < nsyscalls; ++i)
1437 if (sysent[i].sys_func == sys_clone) {
1438 clone_scno[current_personality] = i;
1439 break;
1440 }
1441 }
1442
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001443 if (tcp->s_ent->sys_func == sys_fork ||
1444 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 if (arg_setup(tcp, &state) < 0
1446 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1447 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001448 || change_syscall(tcp, &state,
1449 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001450 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1451 || set_arg1(tcp, &state, 0) < 0
1452 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001454 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1455 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001456 tcp->flags |= TCB_BPTSET;
1457 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001458 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001459
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001460 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001461 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001462 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001463 vfork semantics into plain fork - each application must not
1464 depend on the vfork specifics according to POSIX. We would
1465 hang waiting for the parent resume otherwise. We need to
1466 clear also CLONE_VM but only in the CLONE_VFORK case as
1467 otherwise we would break pthread_create. */
1468
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001469 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1470 if (new_arg0 & CLONE_VFORK)
1471 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1472 if (arg_setup(tcp, &state) < 0
1473 || set_arg0(tcp, &state, new_arg0) < 0
1474 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001475 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001476 tcp->inst[0] = tcp->u_arg[arg0_index];
1477 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001478 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001480 }
1481
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001482 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1483 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484 return -1;
1485}
1486
1487int
Denys Vlasenko12014262011-05-30 14:00:14 +02001488clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001489{
1490 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001491 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001492 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1494 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1495 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001496 if (errno != ESRCH)
1497 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001498 tcp->flags &= ~TCB_BPTSET;
1499 return 0;
1500}