blob: db376b33cc66d85cf7e414da5e64f8f845fa0c9e [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{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000180#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
181# if SUPPORTED_PERSONALITIES > 1
182 if (current_wordsize > 4) {
183# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100184 tprintf(format, tcp->u_arg[arg_no]);
185 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000186# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100187 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000188# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000189 /* Align arg_no to the next even number. */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100190 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000191# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100192 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
193 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100194 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000195# endif /* SUPPORTED_PERSONALITIES */
196#elif SIZEOF_LONG > 4
197# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
198#elif defined LINUX_MIPSN32
199 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100200 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000201#elif defined X32
202 if (current_personality == 0) {
203 tprintf(format, tcp->ext_arg[arg_no]);
204 arg_no++;
205 } else {
206 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
207 arg_no += 2;
208 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100209#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000210# if defined __ARM_EABI__ || \
211 defined LINUX_MIPSO32 || \
212 defined POWERPC || \
213 defined XTENSA
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000214 /* Align arg_no to the next even number. */
215 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000216# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100217 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
218 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100219#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000220
Chris Metcalf879dddd2013-03-01 10:41:02 +0100221 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100222}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100223
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000224/*
225 * Interpret `xlat' as an array of flags
226 * print the entries whose bits are on in `flags'
227 * return # of flags printed.
228 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200229void
Denys Vlasenko12014262011-05-30 14:00:14 +0200230addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200232 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 if (xlat->val && (flags & xlat->val) == xlat->val) {
234 tprintf("|%s", xlat->str);
235 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 }
237 }
238 if (flags) {
239 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241}
242
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000243/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200244 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000245 * Print to static string the entries whose bits are on in `flags'
246 * Return static string.
247 */
248const char *
249sprintflags(const char *prefix, const struct xlat *xlat, int flags)
250{
251 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200252 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253 int found = 0;
254
Denys Vlasenko52845572011-08-31 12:07:38 +0200255 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000256
257 for (; xlat->str; xlat++) {
258 if ((flags & xlat->val) == xlat->val) {
259 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200260 *outptr++ = '|';
261 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000262 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100263 flags &= ~xlat->val;
264 if (!flags)
265 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000266 }
267 }
268 if (flags) {
269 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200270 *outptr++ = '|';
271 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000272 }
273
274 return outstr;
275}
276
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000278printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000279{
280 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000281 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282
283 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200284 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000285 return 1;
286 }
287
288 sep = "";
289 for (n = 0; xlat->str; xlat++) {
290 if (xlat->val && (flags & xlat->val) == xlat->val) {
291 tprintf("%s%s", sep, xlat->str);
292 flags &= ~xlat->val;
293 sep = "|";
294 n++;
295 }
296 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000297
298 if (n) {
299 if (flags) {
300 tprintf("%s%#x", sep, flags);
301 n++;
302 }
303 } else {
304 if (flags) {
305 tprintf("%#x", flags);
306 if (dflt)
307 tprintf(" /* %s */", dflt);
308 } else {
309 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200310 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000311 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314 return n;
315}
316
317void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000318printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
Roland McGratheb285352003-01-14 09:59:00 +0000320 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321
322 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200323 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324 return;
325 }
326 if (umove(tcp, addr, &num) < 0) {
327 tprintf("%#lx", addr);
328 return;
329 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200330 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200332 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333}
334
Roland McGrath6bc12202003-11-13 22:32:27 +0000335void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000336printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000337{
338 int num;
339
340 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200341 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000342 return;
343 }
344 if (umove(tcp, addr, &num) < 0) {
345 tprintf("%#lx", addr);
346 return;
347 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200348 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000349 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200350 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000351}
352
353void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300354printfd(struct tcb *tcp, int fd)
355{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100356 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000357
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100358 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
359 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000360 else
361 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300362}
363
364void
Denys Vlasenko12014262011-05-30 14:00:14 +0200365printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000366{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200367 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000368}
369
Dmitry V. Levina501f142008-11-10 23:19:13 +0000370/*
371 * Quote string `instr' of length `size'
372 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200373 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000374 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100375 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200376 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100377 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000378 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400379int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200380string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000382 const unsigned char *ustr = (const unsigned char *) instr;
383 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200384 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200386 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200387 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200388 size--;
389 eol = '\0';
390 }
391
392 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000393 if (xflag > 1)
394 usehex = 1;
395 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000396 /* Check for presence of symbol which require
397 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000398 for (i = 0; i < size; ++i) {
399 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000400 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200401 if (c == eol)
402 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100403
404 /* Force hex unless c is printable or whitespace */
405 if (c > 0x7e) {
406 usehex = 1;
407 break;
408 }
409 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
410 * They happen to have ASCII codes 9,10,11,12,13.
411 */
412 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000413 usehex = 1;
414 break;
415 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416 }
417 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000418
419 *s++ = '\"';
420
421 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000422 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423 for (i = 0; i < size; ++i) {
424 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000425 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200426 if (c == eol)
427 goto asciz_ended;
428 *s++ = '\\';
429 *s++ = 'x';
430 *s++ = "0123456789abcdef"[c >> 4];
431 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000432 }
433 } else {
434 for (i = 0; i < size; ++i) {
435 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000436 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200437 if (c == eol)
438 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000439 switch (c) {
440 case '\"': case '\\':
441 *s++ = '\\';
442 *s++ = c;
443 break;
444 case '\f':
445 *s++ = '\\';
446 *s++ = 'f';
447 break;
448 case '\n':
449 *s++ = '\\';
450 *s++ = 'n';
451 break;
452 case '\r':
453 *s++ = '\\';
454 *s++ = 'r';
455 break;
456 case '\t':
457 *s++ = '\\';
458 *s++ = 't';
459 break;
460 case '\v':
461 *s++ = '\\';
462 *s++ = 'v';
463 break;
464 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100465 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000466 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200467 else {
468 /* Print \octal */
469 *s++ = '\\';
470 if (i + 1 < size
471 && ustr[i + 1] >= '0'
472 && ustr[i + 1] <= '9'
473 ) {
474 /* Print \ooo */
475 *s++ = '0' + (c >> 6);
476 *s++ = '0' + ((c >> 3) & 0x7);
477 } else {
478 /* Print \[[o]o]o */
479 if ((c >> 3) != 0) {
480 if ((c >> 6) != 0)
481 *s++ = '0' + (c >> 6);
482 *s++ = '0' + ((c >> 3) & 0x7);
483 }
484 }
485 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000486 }
487 break;
488 }
489 }
490 }
491
492 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000494
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200495 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200496 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200497 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
498 * but next char is NUL.
499 */
500 return 0;
501 }
502
503 return 1;
504
505 asciz_ended:
506 *s++ = '\"';
507 *s = '\0';
508 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
509 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510}
511
Dmitry V. Levina501f142008-11-10 23:19:13 +0000512/*
513 * Print path string specified by address `addr' and length `n'.
514 * If path length exceeds `n', append `...' to the output.
515 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000517printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100519 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100520 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100521
Dmitry V. Levina501f142008-11-10 23:19:13 +0000522 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200523 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000524 return;
525 }
526
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100527 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000528 if (n > sizeof path - 1)
529 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000530
531 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100532 nul_seen = umovestr(tcp, addr, n + 1, path);
533 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 tprintf("%#lx", addr);
535 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100536 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000537
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100538 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100539 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100540 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100541 string_quote(path, outstr, -1, n);
542 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100543 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100544 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 }
546}
547
548void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000549printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100551 /* Size must correspond to char path[] size in printpathn */
552 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553}
554
Dmitry V. Levina501f142008-11-10 23:19:13 +0000555/*
556 * Print string specified by address `addr' and length `len'.
557 * If `len' < 0, treat the string as a NUL-terminated string.
558 * If string length exceeds `max_strlen', append `...' to the output.
559 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000560void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200561printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000562{
563 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000565 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100566 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567
568 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200569 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 return;
571 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000572 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200573 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000574 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
575
576 if (outstr_size / 4 != max_strlen)
577 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000578 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200579 if (!str)
580 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000581 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200582 if (!outstr)
583 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000585
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200586 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000587 /*
588 * Treat as a NUL-terminated string: fetch one byte more
589 * because string_quote() quotes one byte less.
590 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000591 size = max_strlen + 1;
592 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593 tprintf("%#lx", addr);
594 return;
595 }
596 }
597 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200598 size = max_strlen;
599 if (size > (unsigned long)len)
600 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000601 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 tprintf("%#lx", addr);
603 return;
604 }
605 }
606
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100607 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
608 * or we were requested to print more than -s NUM chars)...
609 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100610 ellipsis = (string_quote(str, outstr, len, size) &&
611 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000612
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100613 tprints(outstr);
614 if (ellipsis)
615 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000616}
617
John Hughes1d08dcf2001-07-10 13:48:44 +0000618#if HAVE_SYS_UIO_H
619void
Denys Vlasenko12014262011-05-30 14:00:14 +0200620dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000621{
Denys Vlasenko84703742012-02-25 02:38:52 +0100622#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000623 union {
624 struct { u_int32_t base; u_int32_t len; } *iov32;
625 struct { u_int64_t base; u_int64_t len; } *iov64;
626 } iovu;
627#define iov iovu.iov64
628#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100629 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000630#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100631 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000632#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100633 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000634#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000635 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000636#define sizeof_iov sizeof(*iov)
637#define iov_iov_base(i) iov[i].iov_base
638#define iov_iov_len(i) iov[i].iov_len
639#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000640 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200641 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000642
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200643 size = sizeof_iov * len;
644 /* Assuming no sane program has millions of iovs */
645 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000646 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200647 fprintf(stderr, "Out of memory\n");
648 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000649 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000650 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000651 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000652 /* include the buffer number to make it easy to
653 * match up the trace with the source */
654 tprintf(" * %lu bytes in buffer %d\n",
655 (unsigned long)iov_iov_len(i), i);
656 dumpstr(tcp, (long) iov_iov_base(i),
657 iov_iov_len(i));
658 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000659 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200660 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000661#undef sizeof_iov
662#undef iov_iov_base
663#undef iov_iov_len
664#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000665}
666#endif
667
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000668void
Denys Vlasenko12014262011-05-30 14:00:14 +0200669dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670{
671 static int strsize = -1;
672 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673
Denys Vlasenko76325802013-02-22 14:47:39 +0100674 char outbuf[
675 (
676 (sizeof(
677 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
678 "1234567890123456") + /*in case I'm off by few:*/ 4)
679 /*align to 8 to make memset easier:*/ + 7) & -8
680 ];
681 const unsigned char *src;
682 int i;
683
684 memset(outbuf, ' ', sizeof(outbuf));
685
686 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200687 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100688 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200689 if (!str) {
690 strsize = -1;
691 fprintf(stderr, "Out of memory\n");
692 return;
693 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100694 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 }
696
697 if (umoven(tcp, addr, len, (char *) str) < 0)
698 return;
699
Denys Vlasenko76325802013-02-22 14:47:39 +0100700 /* Space-pad to 16 bytes */
701 i = len;
702 while (i & 0xf)
703 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200704
Denys Vlasenko76325802013-02-22 14:47:39 +0100705 i = 0;
706 src = str;
707 while (i < len) {
708 char *dst = outbuf;
709 /* Hex dump */
710 do {
711 if (i < len) {
712 *dst++ = "0123456789abcdef"[*src >> 4];
713 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 }
715 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100716 *dst++ = ' ';
717 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100719 dst++; /* space is there by memset */
720 i++;
721 if ((i & 7) == 0)
722 dst++; /* space is there by memset */
723 src++;
724 } while (i & 0xf);
725 /* ASCII dump */
726 i -= 16;
727 src -= 16;
728 do {
729 if (*src >= ' ' && *src < 0x7f)
730 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000731 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100732 *dst++ = '.';
733 src++;
734 } while (++i & 0xf);
735 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100736 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737 }
738}
739
Mike Frysinger612659e2012-02-14 14:38:28 +0100740#ifdef HAVE_PROCESS_VM_READV
741/* C library supports this, but the kernel might not. */
742static bool process_vm_readv_not_supported = 0;
743#else
744
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100745/* Need to do this since process_vm_readv() is not yet available in libc.
746 * When libc is be updated, only "static bool process_vm_readv_not_supported"
747 * line should remain.
748 */
749#if !defined(__NR_process_vm_readv)
750# if defined(I386)
751# define __NR_process_vm_readv 347
752# elif defined(X86_64)
753# define __NR_process_vm_readv 310
754# elif defined(POWERPC)
755# define __NR_process_vm_readv 351
756# endif
757#endif
758
759#if defined(__NR_process_vm_readv)
760static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400761/* Have to avoid duplicating with the C library headers. */
762static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100763 const struct iovec *lvec,
764 unsigned long liovcnt,
765 const struct iovec *rvec,
766 unsigned long riovcnt,
767 unsigned long flags)
768{
769 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
770}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400771#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100772#else
773static bool process_vm_readv_not_supported = 1;
774# define process_vm_readv(...) (errno = ENOSYS, -1)
775#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100776
777#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100778
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779#define PAGMASK (~(PAGSIZ - 1))
780/*
781 * move `len' bytes of data from process `pid'
782 * at address `addr' to our space at `laddr'
783 */
784int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000785umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000786{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700787 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000788 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789 union {
790 long val;
791 char x[sizeof(long)];
792 } u;
793
Denys Vlasenko2544f982013-02-19 17:39:56 +0100794#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100795 if (current_wordsize < sizeof(addr))
796 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100797#endif
798
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100799 if (!process_vm_readv_not_supported) {
800 struct iovec local[1], remote[1];
801 int r;
802
803 local[0].iov_base = laddr;
804 remote[0].iov_base = (void*)addr;
805 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000806 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100807 if (r == len)
808 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000809 if (r >= 0) {
810 error_msg("umoven: short read (%d < %d) @0x%lx",
811 r, len, addr);
812 return -1;
813 }
814 switch (errno) {
815 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100816 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000817 break;
818 case ESRCH:
819 /* the process is gone */
820 return -1;
821 case EFAULT: case EIO: case EPERM:
822 /* address space is inaccessible */
823 return -1;
824 default:
825 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100826 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000827 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100828 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100829 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100830
Dmitry V. Levin97005922013-02-26 21:16:22 +0000831 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832 if (addr & (sizeof(long) - 1)) {
833 /* addr not a multiple of sizeof(long) */
834 n = addr - (addr & -sizeof(long)); /* residue */
835 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700836 errno = 0;
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000838 switch (errno) {
839 case 0:
840 break;
841 case ESRCH: case EINVAL:
842 /* these could be seen if the process is gone */
843 return -1;
844 case EFAULT: case EIO: case EPERM:
845 /* address space is inaccessible */
846 return -1;
847 default:
848 /* all the rest is strange and should be reported */
849 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
850 pid, addr);
851 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700852 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100853 m = MIN(sizeof(long) - n, len);
854 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100855 addr += sizeof(long);
856 laddr += m;
857 nread += m;
858 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 }
860 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700861 errno = 0;
862 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000863 switch (errno) {
864 case 0:
865 break;
866 case ESRCH: case EINVAL:
867 /* these could be seen if the process is gone */
868 return -1;
869 case EFAULT: case EIO: case EPERM:
870 /* address space is inaccessible */
871 if (nread) {
872 perror_msg("umoven: short read (%d < %d) @0x%lx",
873 nread, nread + len, addr - nread);
874 }
875 return -1;
876 default:
877 /* all the rest is strange and should be reported */
878 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
879 pid, addr);
880 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700881 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100882 m = MIN(sizeof(long), len);
883 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100884 addr += sizeof(long);
885 laddr += m;
886 nread += m;
887 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 return 0;
891}
892
893/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100894 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100896 *
897 * Returns < 0 on error, > 0 if NUL was seen,
898 * (TODO if useful: return count of bytes including NUL),
899 * else 0 if len bytes were read but no NUL byte seen.
900 *
901 * Note: there is no guarantee we won't overwrite some bytes
902 * in laddr[] _after_ terminating NUL (but, of course,
903 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000904 */
905int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000906umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000907{
Denys Vlasenko16940922013-03-01 18:52:59 +0100908#if SIZEOF_LONG == 4
909 const unsigned long x01010101 = 0x01010101ul;
910 const unsigned long x80808080 = 0x80808080ul;
911#elif SIZEOF_LONG == 8
912 const unsigned long x01010101 = 0x0101010101010101ul;
913 const unsigned long x80808080 = 0x8080808080808080ul;
914#else
915# error SIZEOF_LONG > 8
916#endif
917
Roland McGratheb9e2e82009-06-02 16:49:22 -0700918 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100919 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000920 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100921 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 char x[sizeof(long)];
923 } u;
924
Denys Vlasenko2544f982013-02-19 17:39:56 +0100925#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100926 if (current_wordsize < sizeof(addr))
927 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000928#endif
929
Dmitry V. Levin97005922013-02-26 21:16:22 +0000930 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100931 if (!process_vm_readv_not_supported) {
932 struct iovec local[1], remote[1];
933
934 local[0].iov_base = laddr;
935 remote[0].iov_base = (void*)addr;
936
937 while (len > 0) {
938 int end_in_page;
939 int r;
940 int chunk_len;
941
942 /* Don't read kilobytes: most strings are short */
943 chunk_len = len;
944 if (chunk_len > 256)
945 chunk_len = 256;
946 /* Don't cross pages. I guess otherwise we can get EFAULT
947 * and fail to notice that terminating NUL lies
948 * in the existing (first) page.
949 * (I hope there aren't arches with pages < 4K)
950 */
951 end_in_page = ((addr + chunk_len) & 4095);
952 r = chunk_len - end_in_page;
953 if (r > 0) /* if chunk_len > end_in_page */
954 chunk_len = r; /* chunk_len -= end_in_page */
955
956 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000957 r = process_vm_readv(pid, local, 1, remote, 1, 0);
958 if (r > 0) {
959 if (memchr(local[0].iov_base, '\0', r))
960 return 1;
961 local[0].iov_base += r;
962 remote[0].iov_base += r;
963 len -= r;
964 nread += r;
965 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100966 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000967 switch (errno) {
968 case ENOSYS:
969 process_vm_readv_not_supported = 1;
970 goto vm_readv_didnt_work;
971 case ESRCH:
972 /* the process is gone */
973 return -1;
974 case EFAULT: case EIO: case EPERM:
975 /* address space is inaccessible */
976 if (nread) {
977 perror_msg("umovestr: short read (%d < %d) @0x%lx",
978 nread, nread + len, addr);
979 }
980 return -1;
981 default:
982 /* all the rest is strange and should be reported */
983 perror_msg("process_vm_readv");
984 return -1;
985 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100986 }
987 return 0;
988 }
989 vm_readv_didnt_work:
990
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 if (addr & (sizeof(long) - 1)) {
992 /* addr not a multiple of sizeof(long) */
993 n = addr - (addr & -sizeof(long)); /* residue */
994 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700995 errno = 0;
996 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000997 switch (errno) {
998 case 0:
999 break;
1000 case ESRCH: case EINVAL:
1001 /* these could be seen if the process is gone */
1002 return -1;
1003 case EFAULT: case EIO: case EPERM:
1004 /* address space is inaccessible */
1005 return -1;
1006 default:
1007 /* all the rest is strange and should be reported */
1008 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1009 pid, addr);
1010 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001011 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001012 m = MIN(sizeof(long) - n, len);
1013 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 while (n & (sizeof(long) - 1))
1015 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001016 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001017 addr += sizeof(long);
1018 laddr += m;
1019 nread += m;
1020 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001022
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001024 errno = 0;
1025 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001026 switch (errno) {
1027 case 0:
1028 break;
1029 case ESRCH: case EINVAL:
1030 /* these could be seen if the process is gone */
1031 return -1;
1032 case EFAULT: case EIO: case EPERM:
1033 /* address space is inaccessible */
1034 if (nread) {
1035 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1036 nread, nread + len, addr - nread);
1037 }
1038 return -1;
1039 default:
1040 /* all the rest is strange and should be reported */
1041 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1042 pid, addr);
1043 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001044 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001045 m = MIN(sizeof(long), len);
1046 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001047 /* "If a NUL char exists in this word" */
1048 if ((u.val - x01010101) & ~u.val & x80808080)
1049 return 1;
1050 addr += sizeof(long);
1051 laddr += m;
1052 nread += m;
1053 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001055 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056}
1057
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001059upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060{
1061 long val;
1062
Roland McGratheb9e2e82009-06-02 16:49:22 -07001063 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001064 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001065 if (val == -1 && errno) {
1066 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001067 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001068 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001070 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 *res = val;
1072 return 0;
1073}
1074
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001075/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1076 * and PTRACE_O_TRACE[V]FORK for tracing children.
1077 * If you are adding a new arch which is only supported by newer kernels,
1078 * you most likely don't need to add any code below
1079 * beside a dummy "return 0" block in change_syscall().
1080 */
1081
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001082/*
1083 * These #if's are huge, please indent them correctly.
1084 * It's easy to get confused otherwise.
1085 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001087#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001088
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001089#ifndef CLONE_PTRACE
1090# define CLONE_PTRACE 0x00002000
1091#endif
1092#ifndef CLONE_VFORK
1093# define CLONE_VFORK 0x00004000
1094#endif
1095#ifndef CLONE_VM
1096# define CLONE_VM 0x00000100
1097#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001098
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001099#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001100
1101typedef unsigned long *arg_setup_state;
1102
1103static int
1104arg_setup(struct tcb *tcp, arg_setup_state *state)
1105{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001106 unsigned long cfm, sof, sol;
1107 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001108
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001109 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001110 /* Satisfy a false GCC warning. */
1111 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001112 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001113 }
Roland McGrath08267b82004-02-20 22:56:43 +00001114
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001115 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001116 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001117 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001118 return -1;
1119
1120 sof = (cfm >> 0) & 0x7f;
1121 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001122 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001123
Jan Kratochvil1f942712008-08-06 21:38:52 +00001124 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001125 return 0;
1126}
1127
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001128# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001129
Roland McGrathd81f1d92003-01-09 06:53:34 +00001130static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001131get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001132{
Roland McGrath08267b82004-02-20 22:56:43 +00001133 int ret;
1134
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001135 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001136 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001137 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001138 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001139 (unsigned long) ia64_rse_skip_regs(*state, 0),
1140 sizeof(long), (void *) valp);
1141 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001142}
1143
1144static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001145get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001146{
Roland McGrath08267b82004-02-20 22:56:43 +00001147 int ret;
1148
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001149 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001150 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001151 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001152 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001153 (unsigned long) ia64_rse_skip_regs(*state, 1),
1154 sizeof(long), (void *) valp);
1155 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001156}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001157
1158static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001159set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001160{
Roland McGrath08267b82004-02-20 22:56:43 +00001161 int req = PTRACE_POKEDATA;
1162 void *ap;
1163
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001164 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001165 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1166 req = PTRACE_POKEUSER;
1167 } else
1168 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001169 errno = 0;
1170 ptrace(req, tcp->pid, ap, val);
1171 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172}
1173
1174static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001175set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001176{
Roland McGrath08267b82004-02-20 22:56:43 +00001177 int req = PTRACE_POKEDATA;
1178 void *ap;
1179
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001180 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001181 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1182 req = PTRACE_POKEUSER;
1183 } else
1184 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001185 errno = 0;
1186 ptrace(req, tcp->pid, ap, val);
1187 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001188}
1189
Roland McGrathb659f872008-07-18 01:19:36 +00001190/* ia64 does not return the input arguments from functions (and syscalls)
1191 according to ia64 RSE (Register Stack Engine) behavior. */
1192
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001193# define restore_arg0(tcp, state, val) ((void) (state), 0)
1194# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001195
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001196#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001197
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001198# if defined(SPARC64)
1199# undef PTRACE_GETREGS
1200# define PTRACE_GETREGS PTRACE_GETREGS64
1201# undef PTRACE_SETREGS
1202# define PTRACE_SETREGS PTRACE_SETREGS64
1203# endif
1204
Mike Frysinger8566c502009-10-12 11:05:14 -04001205typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001207# define arg_setup(tcp, state) \
1208 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1209# define arg_finish_change(tcp, state) \
1210 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001212# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1213# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1214# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1215# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1216# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001217
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001218#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001219
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001220# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001221/* Note: this is only true for the `clone' system call, which handles
1222 arguments specially. We could as well say that its first two arguments
1223 are swapped relative to other architectures, but that would just be
1224 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001225# define arg0_offset PT_GPR3
1226# define arg1_offset PT_ORIGGPR2
1227# define restore_arg0(tcp, state, val) ((void) (state), 0)
1228# define restore_arg1(tcp, state, val) ((void) (state), 0)
1229# define arg0_index 1
1230# define arg1_index 0
1231# elif defined(ALPHA) || defined(MIPS)
1232# define arg0_offset REG_A0
1233# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001234# elif defined(POWERPC)
1235# define arg0_offset (sizeof(unsigned long)*PT_R3)
1236# define arg1_offset (sizeof(unsigned long)*PT_R4)
1237# define restore_arg0(tcp, state, val) ((void) (state), 0)
1238# elif defined(HPPA)
1239# define arg0_offset PT_GR26
1240# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001241# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001242# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1243# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1244# elif defined(SH)
1245# define arg0_offset (4*(REG_REG0+4))
1246# define arg1_offset (4*(REG_REG0+5))
1247# elif defined(SH64)
1248 /* ABI defines arg0 & 1 in r2 & r3 */
1249# define arg0_offset (REG_OFFSET+16)
1250# define arg1_offset (REG_OFFSET+24)
1251# define restore_arg0(tcp, state, val) 0
1252# elif defined CRISV10 || defined CRISV32
1253# define arg0_offset (4*PT_R11)
1254# define arg1_offset (4*PT_ORIG_R10)
1255# define restore_arg0(tcp, state, val) 0
1256# define restore_arg1(tcp, state, val) 0
1257# define arg0_index 1
1258# define arg1_index 0
1259# else
1260# define arg0_offset 0
1261# define arg1_offset 4
1262# if defined ARM
1263# define restore_arg0(tcp, state, val) 0
1264# endif
1265# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001266
1267typedef int arg_setup_state;
1268
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001269# define arg_setup(tcp, state) (0)
1270# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001271# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1272# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273
1274static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001275set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001276{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001277 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001278}
1279
1280static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001281set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001283 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284}
1285
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001286#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001288#ifndef restore_arg0
1289# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1290#endif
1291#ifndef restore_arg1
1292# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1293#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001294
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001295#ifndef arg0_index
1296# define arg0_index 0
1297# define arg1_index 1
1298#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001299
James Hogan05eb9052012-11-29 17:37:37 +00001300static int
1301change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1302{
1303#if defined(I386)
1304 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1305 return -1;
1306 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001307#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001308 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1309 return -1;
1310 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001311#elif defined(X32)
1312 /* setbpt/clearbpt never used: */
1313 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001314#elif defined(POWERPC)
1315 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1316 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1317 return -1;
1318 return 0;
1319#elif defined(S390) || defined(S390X)
1320 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1321 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1322 return -1;
1323 return 0;
1324#elif defined(M68K)
1325 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1326 return -1;
1327 return 0;
1328#elif defined(SPARC) || defined(SPARC64)
1329 state->u_regs[U_REG_G1] = new;
1330 return 0;
1331#elif defined(MIPS)
1332 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1333 return -1;
1334 return 0;
1335#elif defined(ALPHA)
1336 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1337 return -1;
1338 return 0;
1339#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001340 /* setbpt/clearbpt never used: */
1341 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001342#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001343 /* setbpt/clearbpt never used: */
1344 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001345#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001346 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001347 switch (new) {
1348 case 2:
1349 break; /* x86 SYS_fork */
1350 case SYS_clone:
1351 new = 120;
1352 break;
1353 default:
1354 fprintf(stderr, "%s: unexpected syscall %d\n",
1355 __FUNCTION__, new);
1356 return -1;
1357 }
1358 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1359 return -1;
1360 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1361 return -1;
1362 return 0;
1363#elif defined(HPPA)
1364 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1365 return -1;
1366 return 0;
1367#elif defined(SH)
1368 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1369 return -1;
1370 return 0;
1371#elif defined(SH64)
1372 /* Top half of reg encodes the no. of args n as 0x1n.
1373 Assume 0 args as kernel never actually checks... */
1374 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1375 0x100000 | new) < 0)
1376 return -1;
1377 return 0;
1378#elif defined(CRISV10) || defined(CRISV32)
1379 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1380 return -1;
1381 return 0;
1382#elif defined(ARM)
1383 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1384# ifndef PTRACE_SET_SYSCALL
1385# define PTRACE_SET_SYSCALL 23
1386# endif
1387 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1388 return -1;
1389 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001390#elif defined(AARCH64)
1391 /* setbpt/clearbpt never used: */
1392 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001393#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001394 /* setbpt/clearbpt never used: */
1395 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001396#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001397 /* setbpt/clearbpt never used: */
1398 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001399#elif defined(OR1K)
1400 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001401#elif defined(METAG)
1402 /* setbpt/clearbpt never used: */
1403 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001404#elif defined(XTENSA)
1405 /* setbpt/clearbpt never used: */
1406 /* Xtensa is only supported since linux 2.6.13 */
James Hogan05eb9052012-11-29 17:37:37 +00001407#else
1408#warning Do not know how to handle change_syscall for this architecture
1409#endif /* architecture */
1410 return -1;
1411}
1412
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001414setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001415{
Roland McGrath3291ef22008-05-20 00:34:34 +00001416 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417 arg_setup_state state;
1418
1419 if (tcp->flags & TCB_BPTSET) {
1420 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1421 return -1;
1422 }
1423
Roland McGrath3291ef22008-05-20 00:34:34 +00001424 /*
1425 * It's a silly kludge to initialize this with a search at runtime.
1426 * But it's better than maintaining another magic thing in the
1427 * godforsaken tables.
1428 */
1429 if (clone_scno[current_personality] == 0) {
1430 int i;
1431 for (i = 0; i < nsyscalls; ++i)
1432 if (sysent[i].sys_func == sys_clone) {
1433 clone_scno[current_personality] = i;
1434 break;
1435 }
1436 }
1437
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001438 if (tcp->s_ent->sys_func == sys_fork ||
1439 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001440 if (arg_setup(tcp, &state) < 0
1441 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1442 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001443 || change_syscall(tcp, &state,
1444 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1446 || set_arg1(tcp, &state, 0) < 0
1447 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001448 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001449 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1450 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001451 tcp->flags |= TCB_BPTSET;
1452 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001453 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001454
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001455 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001456 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001457 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001458 vfork semantics into plain fork - each application must not
1459 depend on the vfork specifics according to POSIX. We would
1460 hang waiting for the parent resume otherwise. We need to
1461 clear also CLONE_VM but only in the CLONE_VFORK case as
1462 otherwise we would break pthread_create. */
1463
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001464 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1465 if (new_arg0 & CLONE_VFORK)
1466 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1467 if (arg_setup(tcp, &state) < 0
1468 || set_arg0(tcp, &state, new_arg0) < 0
1469 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001470 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001471 tcp->inst[0] = tcp->u_arg[arg0_index];
1472 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001473 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001474 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001475 }
1476
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001477 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1478 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479 return -1;
1480}
1481
1482int
Denys Vlasenko12014262011-05-30 14:00:14 +02001483clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484{
1485 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001486 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001487 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001488 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1489 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1490 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001491 if (errno != ESRCH)
1492 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001493 tcp->flags &= ~TCB_BPTSET;
1494 return 0;
1495}