blob: 30a7f1950694d2088b5f07afe293b1089da0bc49 [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
Ali Polatel0b4060f2013-09-24 20:04:32 +030058# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
59# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
60# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010061# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030062# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000063# undef ia64_fpreg
64# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000065#endif
66
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000067int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000068string_to_uint(const char *str)
69{
70 char *error;
71 long value;
72
73 if (!*str)
74 return -1;
75 errno = 0;
76 value = strtol(str, &error, 10);
77 if (errno || *error || value < 0 || (long)(int)value != value)
78 return -1;
79 return (int)value;
80}
81
82int
Denys Vlasenko12014262011-05-30 14:00:14 +020083tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084{
85 return a->tv_sec || a->tv_usec;
86}
87
88int
Denys Vlasenko12014262011-05-30 14:00:14 +020089tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090{
91 if (a->tv_sec < b->tv_sec
92 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
93 return -1;
94 if (a->tv_sec > b->tv_sec
95 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
96 return 1;
97 return 0;
98}
99
100double
Denys Vlasenko12014262011-05-30 14:00:14 +0200101tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102{
103 return tv->tv_sec + tv->tv_usec/1000000.0;
104}
105
106void
Denys Vlasenko12014262011-05-30 14:00:14 +0200107tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 tv->tv_sec = a->tv_sec + b->tv_sec;
110 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000111 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112 tv->tv_sec++;
113 tv->tv_usec -= 1000000;
114 }
115}
116
117void
Denys Vlasenko12014262011-05-30 14:00:14 +0200118tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119{
120 tv->tv_sec = a->tv_sec - b->tv_sec;
121 tv->tv_usec = a->tv_usec - b->tv_usec;
122 if (((long) tv->tv_usec) < 0) {
123 tv->tv_sec--;
124 tv->tv_usec += 1000000;
125 }
126}
127
128void
Denys Vlasenko12014262011-05-30 14:00:14 +0200129tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130{
131 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
132 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
133 tv->tv_usec %= 1000000;
134}
135
136void
Denys Vlasenko12014262011-05-30 14:00:14 +0200137tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138{
139 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000140 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141 tv->tv_usec %= 1000000;
142}
143
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000144const char *
145xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146{
147 for (; xlat->str != NULL; xlat++)
148 if (xlat->val == val)
149 return xlat->str;
150 return NULL;
151}
152
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200153#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200154char *
155stpcpy(char *dst, const char *src)
156{
157 while ((*dst = *src++) != '\0')
158 dst++;
159 return dst;
160}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200161#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163/*
164 * Print entry in struct xlat table, if there.
165 */
166void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000167printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000169 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
171 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200172 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173 else
174 tprintf("%#x /* %s */", val, dflt);
175}
176
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100177/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100178 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100179 * argument.
180 */
181int
Chris Metcalf879dddd2013-03-01 10:41:02 +0100182printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100183{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000184#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
185# if SUPPORTED_PERSONALITIES > 1
186 if (current_wordsize > 4) {
187# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100188 tprintf(format, tcp->u_arg[arg_no]);
189 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000190# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100191 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000192# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000193 /* Align arg_no to the next even number. */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100194 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000195# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100196 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
197 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100198 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000199# endif /* SUPPORTED_PERSONALITIES */
200#elif SIZEOF_LONG > 4
201# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
202#elif defined LINUX_MIPSN32
203 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100204 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000205#elif defined X32
206 if (current_personality == 0) {
207 tprintf(format, tcp->ext_arg[arg_no]);
208 arg_no++;
209 } else {
210 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
211 arg_no += 2;
212 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100213#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000214# if defined __ARM_EABI__ || \
215 defined LINUX_MIPSO32 || \
216 defined POWERPC || \
217 defined XTENSA
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000218 /* Align arg_no to the next even number. */
219 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000220# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100221 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
222 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100223#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000224
Chris Metcalf879dddd2013-03-01 10:41:02 +0100225 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100226}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100227
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228/*
229 * Interpret `xlat' as an array of flags
230 * print the entries whose bits are on in `flags'
231 * return # of flags printed.
232 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200233void
Denys Vlasenko12014262011-05-30 14:00:14 +0200234addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200236 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 if (xlat->val && (flags & xlat->val) == xlat->val) {
238 tprintf("|%s", xlat->str);
239 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 }
241 }
242 if (flags) {
243 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000245}
246
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000247/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200248 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000249 * Print to static string the entries whose bits are on in `flags'
250 * Return static string.
251 */
252const char *
253sprintflags(const char *prefix, const struct xlat *xlat, int flags)
254{
255 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200256 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000257 int found = 0;
258
Denys Vlasenko52845572011-08-31 12:07:38 +0200259 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000260
261 for (; xlat->str; xlat++) {
262 if ((flags & xlat->val) == xlat->val) {
263 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200264 *outptr++ = '|';
265 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000266 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100267 flags &= ~xlat->val;
268 if (!flags)
269 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000270 }
271 }
272 if (flags) {
273 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200274 *outptr++ = '|';
275 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000276 }
277
278 return outstr;
279}
280
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000282printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000283{
284 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000285 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286
287 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200288 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289 return 1;
290 }
291
292 sep = "";
293 for (n = 0; xlat->str; xlat++) {
294 if (xlat->val && (flags & xlat->val) == xlat->val) {
295 tprintf("%s%s", sep, xlat->str);
296 flags &= ~xlat->val;
297 sep = "|";
298 n++;
299 }
300 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000301
302 if (n) {
303 if (flags) {
304 tprintf("%s%#x", sep, flags);
305 n++;
306 }
307 } else {
308 if (flags) {
309 tprintf("%#x", flags);
310 if (dflt)
311 tprintf(" /* %s */", dflt);
312 } else {
313 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200314 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000315 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000317
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318 return n;
319}
320
321void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000322printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000323{
Roland McGratheb285352003-01-14 09:59:00 +0000324 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325
326 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200327 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 return;
329 }
330 if (umove(tcp, addr, &num) < 0) {
331 tprintf("%#lx", addr);
332 return;
333 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200334 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000335 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200336 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337}
338
Roland McGrath6bc12202003-11-13 22:32:27 +0000339void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000340printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000341{
342 int num;
343
344 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200345 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000346 return;
347 }
348 if (umove(tcp, addr, &num) < 0) {
349 tprintf("%#lx", addr);
350 return;
351 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200352 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000353 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200354 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000355}
356
357void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300358printfd(struct tcb *tcp, int fd)
359{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100360 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000361
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100362 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
363 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000364 else
365 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300366}
367
368void
Denys Vlasenko12014262011-05-30 14:00:14 +0200369printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000370{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200371 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000372}
373
Dmitry V. Levina501f142008-11-10 23:19:13 +0000374/*
375 * Quote string `instr' of length `size'
376 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200377 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000378 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100379 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200380 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100381 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000382 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400383int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200384string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000386 const unsigned char *ustr = (const unsigned char *) instr;
387 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200388 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200390 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200391 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200392 size--;
393 eol = '\0';
394 }
395
396 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000397 if (xflag > 1)
398 usehex = 1;
399 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000400 /* Check for presence of symbol which require
401 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000402 for (i = 0; i < size; ++i) {
403 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000404 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200405 if (c == eol)
406 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100407
408 /* Force hex unless c is printable or whitespace */
409 if (c > 0x7e) {
410 usehex = 1;
411 break;
412 }
413 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
414 * They happen to have ASCII codes 9,10,11,12,13.
415 */
416 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000417 usehex = 1;
418 break;
419 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000420 }
421 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000422
423 *s++ = '\"';
424
425 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000426 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000427 for (i = 0; i < size; ++i) {
428 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000429 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200430 if (c == eol)
431 goto asciz_ended;
432 *s++ = '\\';
433 *s++ = 'x';
434 *s++ = "0123456789abcdef"[c >> 4];
435 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000436 }
437 } else {
438 for (i = 0; i < size; ++i) {
439 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000440 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200441 if (c == eol)
442 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000443 switch (c) {
444 case '\"': case '\\':
445 *s++ = '\\';
446 *s++ = c;
447 break;
448 case '\f':
449 *s++ = '\\';
450 *s++ = 'f';
451 break;
452 case '\n':
453 *s++ = '\\';
454 *s++ = 'n';
455 break;
456 case '\r':
457 *s++ = '\\';
458 *s++ = 'r';
459 break;
460 case '\t':
461 *s++ = '\\';
462 *s++ = 't';
463 break;
464 case '\v':
465 *s++ = '\\';
466 *s++ = 'v';
467 break;
468 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100469 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000470 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200471 else {
472 /* Print \octal */
473 *s++ = '\\';
474 if (i + 1 < size
475 && ustr[i + 1] >= '0'
476 && ustr[i + 1] <= '9'
477 ) {
478 /* Print \ooo */
479 *s++ = '0' + (c >> 6);
480 *s++ = '0' + ((c >> 3) & 0x7);
481 } else {
482 /* Print \[[o]o]o */
483 if ((c >> 3) != 0) {
484 if ((c >> 6) != 0)
485 *s++ = '0' + (c >> 6);
486 *s++ = '0' + ((c >> 3) & 0x7);
487 }
488 }
489 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000490 }
491 break;
492 }
493 }
494 }
495
496 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000498
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200499 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200500 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200501 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
502 * but next char is NUL.
503 */
504 return 0;
505 }
506
507 return 1;
508
509 asciz_ended:
510 *s++ = '\"';
511 *s = '\0';
512 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
513 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514}
515
Dmitry V. Levina501f142008-11-10 23:19:13 +0000516/*
517 * Print path string specified by address `addr' and length `n'.
518 * If path length exceeds `n', append `...' to the output.
519 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000521printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100523 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100524 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100525
Dmitry V. Levina501f142008-11-10 23:19:13 +0000526 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200527 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528 return;
529 }
530
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100531 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000532 if (n > sizeof path - 1)
533 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000534
535 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100536 nul_seen = umovestr(tcp, addr, n + 1, path);
537 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 tprintf("%#lx", addr);
539 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100540 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000541
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100542 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100543 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100544 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100545 string_quote(path, outstr, -1, n);
546 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100547 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100548 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000549 }
550}
551
552void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000554{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100555 /* Size must correspond to char path[] size in printpathn */
556 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000557}
558
Dmitry V. Levina501f142008-11-10 23:19:13 +0000559/*
560 * Print string specified by address `addr' and length `len'.
561 * If `len' < 0, treat the string as a NUL-terminated string.
562 * If string length exceeds `max_strlen', append `...' to the output.
563 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000564void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200565printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000566{
567 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000569 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100570 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000571
572 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200573 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 return;
575 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000576 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200577 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000578 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
579
580 if (outstr_size / 4 != max_strlen)
581 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000582 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200583 if (!str)
584 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000585 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200586 if (!outstr)
587 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000589
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200590 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000591 /*
592 * Treat as a NUL-terminated string: fetch one byte more
593 * because string_quote() quotes one byte less.
594 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000595 size = max_strlen + 1;
596 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000597 tprintf("%#lx", addr);
598 return;
599 }
600 }
601 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200602 size = max_strlen;
603 if (size > (unsigned long)len)
604 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000605 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 tprintf("%#lx", addr);
607 return;
608 }
609 }
610
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100611 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
612 * or we were requested to print more than -s NUM chars)...
613 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100614 ellipsis = (string_quote(str, outstr, len, size) &&
615 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000616
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100617 tprints(outstr);
618 if (ellipsis)
619 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000620}
621
John Hughes1d08dcf2001-07-10 13:48:44 +0000622#if HAVE_SYS_UIO_H
623void
Denys Vlasenko12014262011-05-30 14:00:14 +0200624dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000625{
Denys Vlasenko84703742012-02-25 02:38:52 +0100626#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000627 union {
628 struct { u_int32_t base; u_int32_t len; } *iov32;
629 struct { u_int64_t base; u_int64_t len; } *iov64;
630 } iovu;
631#define iov iovu.iov64
632#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100633 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000634#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100635 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000636#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100637 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000638#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000639 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000640#define sizeof_iov sizeof(*iov)
641#define iov_iov_base(i) iov[i].iov_base
642#define iov_iov_len(i) iov[i].iov_len
643#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000644 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200645 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000646
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200647 size = sizeof_iov * len;
648 /* Assuming no sane program has millions of iovs */
649 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000650 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200651 fprintf(stderr, "Out of memory\n");
652 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000653 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000654 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000655 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000656 /* include the buffer number to make it easy to
657 * match up the trace with the source */
658 tprintf(" * %lu bytes in buffer %d\n",
659 (unsigned long)iov_iov_len(i), i);
660 dumpstr(tcp, (long) iov_iov_base(i),
661 iov_iov_len(i));
662 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000663 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200664 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000665#undef sizeof_iov
666#undef iov_iov_base
667#undef iov_iov_len
668#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000669}
670#endif
671
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000672void
Denys Vlasenko12014262011-05-30 14:00:14 +0200673dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000674{
675 static int strsize = -1;
676 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000677
Denys Vlasenko76325802013-02-22 14:47:39 +0100678 char outbuf[
679 (
680 (sizeof(
681 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
682 "1234567890123456") + /*in case I'm off by few:*/ 4)
683 /*align to 8 to make memset easier:*/ + 7) & -8
684 ];
685 const unsigned char *src;
686 int i;
687
688 memset(outbuf, ' ', sizeof(outbuf));
689
690 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200691 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100692 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200693 if (!str) {
694 strsize = -1;
695 fprintf(stderr, "Out of memory\n");
696 return;
697 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100698 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699 }
700
701 if (umoven(tcp, addr, len, (char *) str) < 0)
702 return;
703
Denys Vlasenko76325802013-02-22 14:47:39 +0100704 /* Space-pad to 16 bytes */
705 i = len;
706 while (i & 0xf)
707 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200708
Denys Vlasenko76325802013-02-22 14:47:39 +0100709 i = 0;
710 src = str;
711 while (i < len) {
712 char *dst = outbuf;
713 /* Hex dump */
714 do {
715 if (i < len) {
716 *dst++ = "0123456789abcdef"[*src >> 4];
717 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 }
719 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100720 *dst++ = ' ';
721 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100723 dst++; /* space is there by memset */
724 i++;
725 if ((i & 7) == 0)
726 dst++; /* space is there by memset */
727 src++;
728 } while (i & 0xf);
729 /* ASCII dump */
730 i -= 16;
731 src -= 16;
732 do {
733 if (*src >= ' ' && *src < 0x7f)
734 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100736 *dst++ = '.';
737 src++;
738 } while (++i & 0xf);
739 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100740 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000741 }
742}
743
Mike Frysinger612659e2012-02-14 14:38:28 +0100744#ifdef HAVE_PROCESS_VM_READV
745/* C library supports this, but the kernel might not. */
746static bool process_vm_readv_not_supported = 0;
747#else
748
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100749/* Need to do this since process_vm_readv() is not yet available in libc.
750 * When libc is be updated, only "static bool process_vm_readv_not_supported"
751 * line should remain.
752 */
753#if !defined(__NR_process_vm_readv)
754# if defined(I386)
755# define __NR_process_vm_readv 347
756# elif defined(X86_64)
757# define __NR_process_vm_readv 310
758# elif defined(POWERPC)
759# define __NR_process_vm_readv 351
760# endif
761#endif
762
763#if defined(__NR_process_vm_readv)
764static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400765/* Have to avoid duplicating with the C library headers. */
766static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100767 const struct iovec *lvec,
768 unsigned long liovcnt,
769 const struct iovec *rvec,
770 unsigned long riovcnt,
771 unsigned long flags)
772{
773 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
774}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400775#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100776#else
777static bool process_vm_readv_not_supported = 1;
778# define process_vm_readv(...) (errno = ENOSYS, -1)
779#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100780
781#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100782
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783#define PAGMASK (~(PAGSIZ - 1))
784/*
785 * move `len' bytes of data from process `pid'
786 * at address `addr' to our space at `laddr'
787 */
788int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000789umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000790{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700791 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000792 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000793 union {
794 long val;
795 char x[sizeof(long)];
796 } u;
797
Denys Vlasenko2544f982013-02-19 17:39:56 +0100798#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100799 if (current_wordsize < sizeof(addr))
800 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100801#endif
802
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100803 if (!process_vm_readv_not_supported) {
804 struct iovec local[1], remote[1];
805 int r;
806
807 local[0].iov_base = laddr;
808 remote[0].iov_base = (void*)addr;
809 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000810 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100811 if (r == len)
812 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000813 if (r >= 0) {
814 error_msg("umoven: short read (%d < %d) @0x%lx",
815 r, len, addr);
816 return -1;
817 }
818 switch (errno) {
819 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100820 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000821 break;
822 case ESRCH:
823 /* the process is gone */
824 return -1;
825 case EFAULT: case EIO: case EPERM:
826 /* address space is inaccessible */
827 return -1;
828 default:
829 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100830 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000831 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100832 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100833 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100834
Dmitry V. Levin97005922013-02-26 21:16:22 +0000835 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836 if (addr & (sizeof(long) - 1)) {
837 /* addr not a multiple of sizeof(long) */
838 n = addr - (addr & -sizeof(long)); /* residue */
839 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700840 errno = 0;
841 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000842 switch (errno) {
843 case 0:
844 break;
845 case ESRCH: case EINVAL:
846 /* these could be seen if the process is gone */
847 return -1;
848 case EFAULT: case EIO: case EPERM:
849 /* address space is inaccessible */
850 return -1;
851 default:
852 /* all the rest is strange and should be reported */
853 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
854 pid, addr);
855 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700856 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100857 m = MIN(sizeof(long) - n, len);
858 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100859 addr += sizeof(long);
860 laddr += m;
861 nread += m;
862 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 }
864 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700865 errno = 0;
866 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000867 switch (errno) {
868 case 0:
869 break;
870 case ESRCH: case EINVAL:
871 /* these could be seen if the process is gone */
872 return -1;
873 case EFAULT: case EIO: case EPERM:
874 /* address space is inaccessible */
875 if (nread) {
876 perror_msg("umoven: short read (%d < %d) @0x%lx",
877 nread, nread + len, addr - nread);
878 }
879 return -1;
880 default:
881 /* all the rest is strange and should be reported */
882 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
883 pid, addr);
884 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700885 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100886 m = MIN(sizeof(long), len);
887 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100888 addr += sizeof(long);
889 laddr += m;
890 nread += m;
891 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 return 0;
895}
896
897/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100898 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000899 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100900 *
901 * Returns < 0 on error, > 0 if NUL was seen,
902 * (TODO if useful: return count of bytes including NUL),
903 * else 0 if len bytes were read but no NUL byte seen.
904 *
905 * Note: there is no guarantee we won't overwrite some bytes
906 * in laddr[] _after_ terminating NUL (but, of course,
907 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 */
909int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000910umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911{
Denys Vlasenko16940922013-03-01 18:52:59 +0100912#if SIZEOF_LONG == 4
913 const unsigned long x01010101 = 0x01010101ul;
914 const unsigned long x80808080 = 0x80808080ul;
915#elif SIZEOF_LONG == 8
916 const unsigned long x01010101 = 0x0101010101010101ul;
917 const unsigned long x80808080 = 0x8080808080808080ul;
918#else
919# error SIZEOF_LONG > 8
920#endif
921
Roland McGratheb9e2e82009-06-02 16:49:22 -0700922 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100923 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100925 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 char x[sizeof(long)];
927 } u;
928
Denys Vlasenko2544f982013-02-19 17:39:56 +0100929#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100930 if (current_wordsize < sizeof(addr))
931 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000932#endif
933
Dmitry V. Levin97005922013-02-26 21:16:22 +0000934 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100935 if (!process_vm_readv_not_supported) {
936 struct iovec local[1], remote[1];
937
938 local[0].iov_base = laddr;
939 remote[0].iov_base = (void*)addr;
940
941 while (len > 0) {
942 int end_in_page;
943 int r;
944 int chunk_len;
945
946 /* Don't read kilobytes: most strings are short */
947 chunk_len = len;
948 if (chunk_len > 256)
949 chunk_len = 256;
950 /* Don't cross pages. I guess otherwise we can get EFAULT
951 * and fail to notice that terminating NUL lies
952 * in the existing (first) page.
953 * (I hope there aren't arches with pages < 4K)
954 */
955 end_in_page = ((addr + chunk_len) & 4095);
956 r = chunk_len - end_in_page;
957 if (r > 0) /* if chunk_len > end_in_page */
958 chunk_len = r; /* chunk_len -= end_in_page */
959
960 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000961 r = process_vm_readv(pid, local, 1, remote, 1, 0);
962 if (r > 0) {
963 if (memchr(local[0].iov_base, '\0', r))
964 return 1;
965 local[0].iov_base += r;
966 remote[0].iov_base += r;
967 len -= r;
968 nread += r;
969 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100970 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000971 switch (errno) {
972 case ENOSYS:
973 process_vm_readv_not_supported = 1;
974 goto vm_readv_didnt_work;
975 case ESRCH:
976 /* the process is gone */
977 return -1;
978 case EFAULT: case EIO: case EPERM:
979 /* address space is inaccessible */
980 if (nread) {
981 perror_msg("umovestr: short read (%d < %d) @0x%lx",
982 nread, nread + len, addr);
983 }
984 return -1;
985 default:
986 /* all the rest is strange and should be reported */
987 perror_msg("process_vm_readv");
988 return -1;
989 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100990 }
991 return 0;
992 }
993 vm_readv_didnt_work:
994
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 if (addr & (sizeof(long) - 1)) {
996 /* addr not a multiple of sizeof(long) */
997 n = addr - (addr & -sizeof(long)); /* residue */
998 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700999 errno = 0;
1000 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001001 switch (errno) {
1002 case 0:
1003 break;
1004 case ESRCH: case EINVAL:
1005 /* these could be seen if the process is gone */
1006 return -1;
1007 case EFAULT: case EIO: case EPERM:
1008 /* address space is inaccessible */
1009 return -1;
1010 default:
1011 /* all the rest is strange and should be reported */
1012 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1013 pid, addr);
1014 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001015 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001016 m = MIN(sizeof(long) - n, len);
1017 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 while (n & (sizeof(long) - 1))
1019 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001020 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001021 addr += sizeof(long);
1022 laddr += m;
1023 nread += m;
1024 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001026
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001028 errno = 0;
1029 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001030 switch (errno) {
1031 case 0:
1032 break;
1033 case ESRCH: case EINVAL:
1034 /* these could be seen if the process is gone */
1035 return -1;
1036 case EFAULT: case EIO: case EPERM:
1037 /* address space is inaccessible */
1038 if (nread) {
1039 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1040 nread, nread + len, addr - nread);
1041 }
1042 return -1;
1043 default:
1044 /* all the rest is strange and should be reported */
1045 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1046 pid, addr);
1047 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001048 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001049 m = MIN(sizeof(long), len);
1050 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001051 /* "If a NUL char exists in this word" */
1052 if ((u.val - x01010101) & ~u.val & x80808080)
1053 return 1;
1054 addr += sizeof(long);
1055 laddr += m;
1056 nread += m;
1057 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001059 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060}
1061
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001063upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064{
1065 long val;
1066
Roland McGratheb9e2e82009-06-02 16:49:22 -07001067 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001068 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001069 if (val == -1 && errno) {
1070 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001071 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001072 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001074 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 *res = val;
1076 return 0;
1077}
1078
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001079/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1080 * and PTRACE_O_TRACE[V]FORK for tracing children.
1081 * If you are adding a new arch which is only supported by newer kernels,
1082 * you most likely don't need to add any code below
1083 * beside a dummy "return 0" block in change_syscall().
1084 */
1085
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001086/*
1087 * These #if's are huge, please indent them correctly.
1088 * It's easy to get confused otherwise.
1089 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001090
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001091#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001092
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001093#ifndef CLONE_PTRACE
1094# define CLONE_PTRACE 0x00002000
1095#endif
1096#ifndef CLONE_VFORK
1097# define CLONE_VFORK 0x00004000
1098#endif
1099#ifndef CLONE_VM
1100# define CLONE_VM 0x00000100
1101#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001102
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001103#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001104
1105typedef unsigned long *arg_setup_state;
1106
1107static int
1108arg_setup(struct tcb *tcp, arg_setup_state *state)
1109{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001110 unsigned long cfm, sof, sol;
1111 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001112
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001113 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001114 /* Satisfy a false GCC warning. */
1115 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001116 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001117 }
Roland McGrath08267b82004-02-20 22:56:43 +00001118
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001119 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001120 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001121 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001122 return -1;
1123
1124 sof = (cfm >> 0) & 0x7f;
1125 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001126 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001127
Jan Kratochvil1f942712008-08-06 21:38:52 +00001128 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001129 return 0;
1130}
1131
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001132# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001133
Roland McGrathd81f1d92003-01-09 06:53:34 +00001134static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001135get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001136{
Roland McGrath08267b82004-02-20 22:56:43 +00001137 int ret;
1138
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001139 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001140 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001141 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001142 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001143 (unsigned long) ia64_rse_skip_regs(*state, 0),
1144 sizeof(long), (void *) valp);
1145 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001146}
1147
1148static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001149get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001150{
Roland McGrath08267b82004-02-20 22:56:43 +00001151 int ret;
1152
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001153 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001154 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001155 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001156 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001157 (unsigned long) ia64_rse_skip_regs(*state, 1),
1158 sizeof(long), (void *) valp);
1159 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001160}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001161
1162static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001163set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001164{
Roland McGrath08267b82004-02-20 22:56:43 +00001165 int req = PTRACE_POKEDATA;
1166 void *ap;
1167
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001168 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001169 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1170 req = PTRACE_POKEUSER;
1171 } else
1172 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001173 errno = 0;
1174 ptrace(req, tcp->pid, ap, val);
1175 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001176}
1177
1178static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001179set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180{
Roland McGrath08267b82004-02-20 22:56:43 +00001181 int req = PTRACE_POKEDATA;
1182 void *ap;
1183
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001184 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001185 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1186 req = PTRACE_POKEUSER;
1187 } else
1188 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001189 errno = 0;
1190 ptrace(req, tcp->pid, ap, val);
1191 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001192}
1193
Roland McGrathb659f872008-07-18 01:19:36 +00001194/* ia64 does not return the input arguments from functions (and syscalls)
1195 according to ia64 RSE (Register Stack Engine) behavior. */
1196
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001197# define restore_arg0(tcp, state, val) ((void) (state), 0)
1198# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001199
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001200#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001201
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001202# if defined(SPARC64)
1203# undef PTRACE_GETREGS
1204# define PTRACE_GETREGS PTRACE_GETREGS64
1205# undef PTRACE_SETREGS
1206# define PTRACE_SETREGS PTRACE_SETREGS64
1207# endif
1208
Mike Frysinger8566c502009-10-12 11:05:14 -04001209typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001210
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001211# define arg_setup(tcp, state) \
1212 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1213# define arg_finish_change(tcp, state) \
1214 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001215
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001216# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1217# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1218# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1219# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1220# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001221
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001222#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001223
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001224# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001225/* Note: this is only true for the `clone' system call, which handles
1226 arguments specially. We could as well say that its first two arguments
1227 are swapped relative to other architectures, but that would just be
1228 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001229# define arg0_offset PT_GPR3
1230# define arg1_offset PT_ORIGGPR2
1231# define restore_arg0(tcp, state, val) ((void) (state), 0)
1232# define restore_arg1(tcp, state, val) ((void) (state), 0)
1233# define arg0_index 1
1234# define arg1_index 0
1235# elif defined(ALPHA) || defined(MIPS)
1236# define arg0_offset REG_A0
1237# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001238# elif defined(POWERPC)
1239# define arg0_offset (sizeof(unsigned long)*PT_R3)
1240# define arg1_offset (sizeof(unsigned long)*PT_R4)
1241# define restore_arg0(tcp, state, val) ((void) (state), 0)
1242# elif defined(HPPA)
1243# define arg0_offset PT_GR26
1244# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001245# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001246# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1247# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1248# elif defined(SH)
1249# define arg0_offset (4*(REG_REG0+4))
1250# define arg1_offset (4*(REG_REG0+5))
1251# elif defined(SH64)
1252 /* ABI defines arg0 & 1 in r2 & r3 */
1253# define arg0_offset (REG_OFFSET+16)
1254# define arg1_offset (REG_OFFSET+24)
1255# define restore_arg0(tcp, state, val) 0
1256# elif defined CRISV10 || defined CRISV32
1257# define arg0_offset (4*PT_R11)
1258# define arg1_offset (4*PT_ORIG_R10)
1259# define restore_arg0(tcp, state, val) 0
1260# define restore_arg1(tcp, state, val) 0
1261# define arg0_index 1
1262# define arg1_index 0
1263# else
1264# define arg0_offset 0
1265# define arg1_offset 4
1266# if defined ARM
1267# define restore_arg0(tcp, state, val) 0
1268# endif
1269# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270
1271typedef int arg_setup_state;
1272
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001273# define arg_setup(tcp, state) (0)
1274# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001275# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1276# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277
1278static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001279set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001280{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001281 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282}
1283
1284static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001285set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001287 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001288}
1289
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001290#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001292#ifndef restore_arg0
1293# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1294#endif
1295#ifndef restore_arg1
1296# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1297#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001298
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001299#ifndef arg0_index
1300# define arg0_index 0
1301# define arg1_index 1
1302#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001303
James Hogan05eb9052012-11-29 17:37:37 +00001304static int
1305change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1306{
1307#if defined(I386)
1308 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1309 return -1;
1310 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001311#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001312 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1313 return -1;
1314 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001315#elif defined(X32)
1316 /* setbpt/clearbpt never used: */
1317 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001318#elif defined(POWERPC)
1319 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1320 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1321 return -1;
1322 return 0;
1323#elif defined(S390) || defined(S390X)
1324 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1325 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1326 return -1;
1327 return 0;
1328#elif defined(M68K)
1329 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1330 return -1;
1331 return 0;
1332#elif defined(SPARC) || defined(SPARC64)
1333 state->u_regs[U_REG_G1] = new;
1334 return 0;
1335#elif defined(MIPS)
1336 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1337 return -1;
1338 return 0;
1339#elif defined(ALPHA)
1340 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1341 return -1;
1342 return 0;
1343#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001344 /* setbpt/clearbpt never used: */
1345 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001346#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001347 /* setbpt/clearbpt never used: */
1348 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001349#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001350 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001351 switch (new) {
1352 case 2:
1353 break; /* x86 SYS_fork */
1354 case SYS_clone:
1355 new = 120;
1356 break;
1357 default:
1358 fprintf(stderr, "%s: unexpected syscall %d\n",
1359 __FUNCTION__, new);
1360 return -1;
1361 }
1362 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1363 return -1;
1364 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1365 return -1;
1366 return 0;
1367#elif defined(HPPA)
1368 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1369 return -1;
1370 return 0;
1371#elif defined(SH)
1372 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1373 return -1;
1374 return 0;
1375#elif defined(SH64)
1376 /* Top half of reg encodes the no. of args n as 0x1n.
1377 Assume 0 args as kernel never actually checks... */
1378 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1379 0x100000 | new) < 0)
1380 return -1;
1381 return 0;
1382#elif defined(CRISV10) || defined(CRISV32)
1383 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1384 return -1;
1385 return 0;
1386#elif defined(ARM)
1387 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1388# ifndef PTRACE_SET_SYSCALL
1389# define PTRACE_SET_SYSCALL 23
1390# endif
1391 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1392 return -1;
1393 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001394#elif defined(AARCH64)
1395 /* setbpt/clearbpt never used: */
1396 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001397#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001398 /* setbpt/clearbpt never used: */
1399 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001400#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001401 /* setbpt/clearbpt never used: */
1402 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001403#elif defined(OR1K)
1404 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001405#elif defined(METAG)
1406 /* setbpt/clearbpt never used: */
1407 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001408#elif defined(XTENSA)
1409 /* setbpt/clearbpt never used: */
1410 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301411#elif defined(ARC)
1412 /* setbpt/clearbpt never used: */
1413 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001414#else
1415#warning Do not know how to handle change_syscall for this architecture
1416#endif /* architecture */
1417 return -1;
1418}
1419
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001421setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422{
Roland McGrath3291ef22008-05-20 00:34:34 +00001423 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001424 arg_setup_state state;
1425
1426 if (tcp->flags & TCB_BPTSET) {
1427 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1428 return -1;
1429 }
1430
Roland McGrath3291ef22008-05-20 00:34:34 +00001431 /*
1432 * It's a silly kludge to initialize this with a search at runtime.
1433 * But it's better than maintaining another magic thing in the
1434 * godforsaken tables.
1435 */
1436 if (clone_scno[current_personality] == 0) {
1437 int i;
1438 for (i = 0; i < nsyscalls; ++i)
1439 if (sysent[i].sys_func == sys_clone) {
1440 clone_scno[current_personality] = i;
1441 break;
1442 }
1443 }
1444
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001445 if (tcp->s_ent->sys_func == sys_fork ||
1446 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001447 if (arg_setup(tcp, &state) < 0
1448 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1449 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001450 || change_syscall(tcp, &state,
1451 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001452 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1453 || set_arg1(tcp, &state, 0) < 0
1454 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001456 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1457 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001458 tcp->flags |= TCB_BPTSET;
1459 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001460 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001461
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001462 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001463 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001464 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001465 vfork semantics into plain fork - each application must not
1466 depend on the vfork specifics according to POSIX. We would
1467 hang waiting for the parent resume otherwise. We need to
1468 clear also CLONE_VM but only in the CLONE_VFORK case as
1469 otherwise we would break pthread_create. */
1470
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001471 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1472 if (new_arg0 & CLONE_VFORK)
1473 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1474 if (arg_setup(tcp, &state) < 0
1475 || set_arg0(tcp, &state, new_arg0) < 0
1476 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001477 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001478 tcp->inst[0] = tcp->u_arg[arg0_index];
1479 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001480 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001482 }
1483
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001484 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1485 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001486 return -1;
1487}
1488
1489int
Denys Vlasenko12014262011-05-30 14:00:14 +02001490clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001491{
1492 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001494 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001495 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1496 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1497 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001498 if (errno != ESRCH)
1499 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001500 tcp->flags &= ~TCB_BPTSET;
1501 return 0;
1502}