blob: 970faa44b1cc4274b34118ae930d99f7ab8041b5 [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. Levin7a498be2013-05-04 19:51:57 +0000210# if defined(ARM) || defined(POWERPC)
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000211 /* Align arg_no to the next even number. */
212 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000213# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100214 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
215 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100216#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000217
Chris Metcalf879dddd2013-03-01 10:41:02 +0100218 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100219}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100220
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000221/*
222 * Interpret `xlat' as an array of flags
223 * print the entries whose bits are on in `flags'
224 * return # of flags printed.
225 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200226void
Denys Vlasenko12014262011-05-30 14:00:14 +0200227addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200229 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230 if (xlat->val && (flags & xlat->val) == xlat->val) {
231 tprintf("|%s", xlat->str);
232 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 }
234 }
235 if (flags) {
236 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238}
239
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000240/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200241 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000242 * Print to static string the entries whose bits are on in `flags'
243 * Return static string.
244 */
245const char *
246sprintflags(const char *prefix, const struct xlat *xlat, int flags)
247{
248 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200249 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000250 int found = 0;
251
Denys Vlasenko52845572011-08-31 12:07:38 +0200252 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253
254 for (; xlat->str; xlat++) {
255 if ((flags & xlat->val) == xlat->val) {
256 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200257 *outptr++ = '|';
258 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000259 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100260 flags &= ~xlat->val;
261 if (!flags)
262 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000263 }
264 }
265 if (flags) {
266 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200267 *outptr++ = '|';
268 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000269 }
270
271 return outstr;
272}
273
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000274int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000275printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000276{
277 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000278 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000279
280 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200281 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282 return 1;
283 }
284
285 sep = "";
286 for (n = 0; xlat->str; xlat++) {
287 if (xlat->val && (flags & xlat->val) == xlat->val) {
288 tprintf("%s%s", sep, xlat->str);
289 flags &= ~xlat->val;
290 sep = "|";
291 n++;
292 }
293 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000294
295 if (n) {
296 if (flags) {
297 tprintf("%s%#x", sep, flags);
298 n++;
299 }
300 } else {
301 if (flags) {
302 tprintf("%#x", flags);
303 if (dflt)
304 tprintf(" /* %s */", dflt);
305 } else {
306 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200307 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000308 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000310
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 return n;
312}
313
314void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000315printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316{
Roland McGratheb285352003-01-14 09:59:00 +0000317 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318
319 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200320 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 return;
322 }
323 if (umove(tcp, addr, &num) < 0) {
324 tprintf("%#lx", addr);
325 return;
326 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200327 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200329 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000330}
331
Roland McGrath6bc12202003-11-13 22:32:27 +0000332void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000333printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000334{
335 int num;
336
337 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200338 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000339 return;
340 }
341 if (umove(tcp, addr, &num) < 0) {
342 tprintf("%#lx", addr);
343 return;
344 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200345 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000346 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200347 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000348}
349
350void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300351printfd(struct tcb *tcp, int fd)
352{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100353 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000354
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100355 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
356 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000357 else
358 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300359}
360
361void
Denys Vlasenko12014262011-05-30 14:00:14 +0200362printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000363{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200364 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000365}
366
Dmitry V. Levina501f142008-11-10 23:19:13 +0000367/*
368 * Quote string `instr' of length `size'
369 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200370 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000371 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100372 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200373 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100374 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000375 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400376int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200377string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000378{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000379 const unsigned char *ustr = (const unsigned char *) instr;
380 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200381 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200383 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200384 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200385 size--;
386 eol = '\0';
387 }
388
389 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000390 if (xflag > 1)
391 usehex = 1;
392 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000393 /* Check for presence of symbol which require
394 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000395 for (i = 0; i < size; ++i) {
396 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000397 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200398 if (c == eol)
399 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100400
401 /* Force hex unless c is printable or whitespace */
402 if (c > 0x7e) {
403 usehex = 1;
404 break;
405 }
406 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
407 * They happen to have ASCII codes 9,10,11,12,13.
408 */
409 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000410 usehex = 1;
411 break;
412 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000413 }
414 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000415
416 *s++ = '\"';
417
418 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000419 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000420 for (i = 0; i < size; ++i) {
421 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000422 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200423 if (c == eol)
424 goto asciz_ended;
425 *s++ = '\\';
426 *s++ = 'x';
427 *s++ = "0123456789abcdef"[c >> 4];
428 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000429 }
430 } else {
431 for (i = 0; i < size; ++i) {
432 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000433 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200434 if (c == eol)
435 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000436 switch (c) {
437 case '\"': case '\\':
438 *s++ = '\\';
439 *s++ = c;
440 break;
441 case '\f':
442 *s++ = '\\';
443 *s++ = 'f';
444 break;
445 case '\n':
446 *s++ = '\\';
447 *s++ = 'n';
448 break;
449 case '\r':
450 *s++ = '\\';
451 *s++ = 'r';
452 break;
453 case '\t':
454 *s++ = '\\';
455 *s++ = 't';
456 break;
457 case '\v':
458 *s++ = '\\';
459 *s++ = 'v';
460 break;
461 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100462 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000463 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200464 else {
465 /* Print \octal */
466 *s++ = '\\';
467 if (i + 1 < size
468 && ustr[i + 1] >= '0'
469 && ustr[i + 1] <= '9'
470 ) {
471 /* Print \ooo */
472 *s++ = '0' + (c >> 6);
473 *s++ = '0' + ((c >> 3) & 0x7);
474 } else {
475 /* Print \[[o]o]o */
476 if ((c >> 3) != 0) {
477 if ((c >> 6) != 0)
478 *s++ = '0' + (c >> 6);
479 *s++ = '0' + ((c >> 3) & 0x7);
480 }
481 }
482 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000483 }
484 break;
485 }
486 }
487 }
488
489 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000490 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000491
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200492 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200493 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200494 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
495 * but next char is NUL.
496 */
497 return 0;
498 }
499
500 return 1;
501
502 asciz_ended:
503 *s++ = '\"';
504 *s = '\0';
505 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
506 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507}
508
Dmitry V. Levina501f142008-11-10 23:19:13 +0000509/*
510 * Print path string specified by address `addr' and length `n'.
511 * If path length exceeds `n', append `...' to the output.
512 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000513void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000514printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100516 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100517 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100518
Dmitry V. Levina501f142008-11-10 23:19:13 +0000519 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200520 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000521 return;
522 }
523
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100524 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000525 if (n > sizeof path - 1)
526 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000527
528 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100529 nul_seen = umovestr(tcp, addr, n + 1, path);
530 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 tprintf("%#lx", addr);
532 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100533 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000534
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100535 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100536 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100537 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100538 string_quote(path, outstr, -1, n);
539 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100540 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100541 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 }
543}
544
545void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000546printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100548 /* Size must correspond to char path[] size in printpathn */
549 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550}
551
Dmitry V. Levina501f142008-11-10 23:19:13 +0000552/*
553 * Print string specified by address `addr' and length `len'.
554 * If `len' < 0, treat the string as a NUL-terminated string.
555 * If string length exceeds `max_strlen', append `...' to the output.
556 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000557void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200558printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000559{
560 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000562 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100563 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564
565 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200566 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 return;
568 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200570 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000571 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
572
573 if (outstr_size / 4 != max_strlen)
574 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000575 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200576 if (!str)
577 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000578 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200579 if (!outstr)
580 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000582
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200583 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000584 /*
585 * Treat as a NUL-terminated string: fetch one byte more
586 * because string_quote() quotes one byte less.
587 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000588 size = max_strlen + 1;
589 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590 tprintf("%#lx", addr);
591 return;
592 }
593 }
594 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200595 size = max_strlen;
596 if (size > (unsigned long)len)
597 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000598 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599 tprintf("%#lx", addr);
600 return;
601 }
602 }
603
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100604 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
605 * or we were requested to print more than -s NUM chars)...
606 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100607 ellipsis = (string_quote(str, outstr, len, size) &&
608 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000609
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100610 tprints(outstr);
611 if (ellipsis)
612 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000613}
614
John Hughes1d08dcf2001-07-10 13:48:44 +0000615#if HAVE_SYS_UIO_H
616void
Denys Vlasenko12014262011-05-30 14:00:14 +0200617dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000618{
Denys Vlasenko84703742012-02-25 02:38:52 +0100619#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000620 union {
621 struct { u_int32_t base; u_int32_t len; } *iov32;
622 struct { u_int64_t base; u_int64_t len; } *iov64;
623 } iovu;
624#define iov iovu.iov64
625#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100626 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000627#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100628 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000629#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100630 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000631#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000632 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000633#define sizeof_iov sizeof(*iov)
634#define iov_iov_base(i) iov[i].iov_base
635#define iov_iov_len(i) iov[i].iov_len
636#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000637 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200638 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000639
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200640 size = sizeof_iov * len;
641 /* Assuming no sane program has millions of iovs */
642 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000643 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200644 fprintf(stderr, "Out of memory\n");
645 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000646 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000647 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000648 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000649 /* include the buffer number to make it easy to
650 * match up the trace with the source */
651 tprintf(" * %lu bytes in buffer %d\n",
652 (unsigned long)iov_iov_len(i), i);
653 dumpstr(tcp, (long) iov_iov_base(i),
654 iov_iov_len(i));
655 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000656 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200657 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000658#undef sizeof_iov
659#undef iov_iov_base
660#undef iov_iov_len
661#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000662}
663#endif
664
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665void
Denys Vlasenko12014262011-05-30 14:00:14 +0200666dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667{
668 static int strsize = -1;
669 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670
Denys Vlasenko76325802013-02-22 14:47:39 +0100671 char outbuf[
672 (
673 (sizeof(
674 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
675 "1234567890123456") + /*in case I'm off by few:*/ 4)
676 /*align to 8 to make memset easier:*/ + 7) & -8
677 ];
678 const unsigned char *src;
679 int i;
680
681 memset(outbuf, ' ', sizeof(outbuf));
682
683 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200684 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100685 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200686 if (!str) {
687 strsize = -1;
688 fprintf(stderr, "Out of memory\n");
689 return;
690 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100691 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 }
693
694 if (umoven(tcp, addr, len, (char *) str) < 0)
695 return;
696
Denys Vlasenko76325802013-02-22 14:47:39 +0100697 /* Space-pad to 16 bytes */
698 i = len;
699 while (i & 0xf)
700 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200701
Denys Vlasenko76325802013-02-22 14:47:39 +0100702 i = 0;
703 src = str;
704 while (i < len) {
705 char *dst = outbuf;
706 /* Hex dump */
707 do {
708 if (i < len) {
709 *dst++ = "0123456789abcdef"[*src >> 4];
710 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000711 }
712 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100713 *dst++ = ' ';
714 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100716 dst++; /* space is there by memset */
717 i++;
718 if ((i & 7) == 0)
719 dst++; /* space is there by memset */
720 src++;
721 } while (i & 0xf);
722 /* ASCII dump */
723 i -= 16;
724 src -= 16;
725 do {
726 if (*src >= ' ' && *src < 0x7f)
727 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100729 *dst++ = '.';
730 src++;
731 } while (++i & 0xf);
732 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100733 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734 }
735}
736
Mike Frysinger612659e2012-02-14 14:38:28 +0100737#ifdef HAVE_PROCESS_VM_READV
738/* C library supports this, but the kernel might not. */
739static bool process_vm_readv_not_supported = 0;
740#else
741
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100742/* Need to do this since process_vm_readv() is not yet available in libc.
743 * When libc is be updated, only "static bool process_vm_readv_not_supported"
744 * line should remain.
745 */
746#if !defined(__NR_process_vm_readv)
747# if defined(I386)
748# define __NR_process_vm_readv 347
749# elif defined(X86_64)
750# define __NR_process_vm_readv 310
751# elif defined(POWERPC)
752# define __NR_process_vm_readv 351
753# endif
754#endif
755
756#if defined(__NR_process_vm_readv)
757static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400758/* Have to avoid duplicating with the C library headers. */
759static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100760 const struct iovec *lvec,
761 unsigned long liovcnt,
762 const struct iovec *rvec,
763 unsigned long riovcnt,
764 unsigned long flags)
765{
766 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
767}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400768#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100769#else
770static bool process_vm_readv_not_supported = 1;
771# define process_vm_readv(...) (errno = ENOSYS, -1)
772#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100773
774#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100775
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776#define PAGMASK (~(PAGSIZ - 1))
777/*
778 * move `len' bytes of data from process `pid'
779 * at address `addr' to our space at `laddr'
780 */
781int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000782umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700784 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000785 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000786 union {
787 long val;
788 char x[sizeof(long)];
789 } u;
790
Denys Vlasenko2544f982013-02-19 17:39:56 +0100791#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100792 if (current_wordsize < sizeof(addr))
793 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100794#endif
795
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100796 if (!process_vm_readv_not_supported) {
797 struct iovec local[1], remote[1];
798 int r;
799
800 local[0].iov_base = laddr;
801 remote[0].iov_base = (void*)addr;
802 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000803 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100804 if (r == len)
805 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000806 if (r >= 0) {
807 error_msg("umoven: short read (%d < %d) @0x%lx",
808 r, len, addr);
809 return -1;
810 }
811 switch (errno) {
812 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100813 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000814 break;
815 case ESRCH:
816 /* the process is gone */
817 return -1;
818 case EFAULT: case EIO: case EPERM:
819 /* address space is inaccessible */
820 return -1;
821 default:
822 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100823 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000824 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100825 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100826 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100827
Dmitry V. Levin97005922013-02-26 21:16:22 +0000828 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829 if (addr & (sizeof(long) - 1)) {
830 /* addr not a multiple of sizeof(long) */
831 n = addr - (addr & -sizeof(long)); /* residue */
832 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700833 errno = 0;
834 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000835 switch (errno) {
836 case 0:
837 break;
838 case ESRCH: case EINVAL:
839 /* these could be seen if the process is gone */
840 return -1;
841 case EFAULT: case EIO: case EPERM:
842 /* address space is inaccessible */
843 return -1;
844 default:
845 /* all the rest is strange and should be reported */
846 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
847 pid, addr);
848 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700849 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100850 m = MIN(sizeof(long) - n, len);
851 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100852 addr += sizeof(long);
853 laddr += m;
854 nread += m;
855 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000856 }
857 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700858 errno = 0;
859 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000860 switch (errno) {
861 case 0:
862 break;
863 case ESRCH: case EINVAL:
864 /* these could be seen if the process is gone */
865 return -1;
866 case EFAULT: case EIO: case EPERM:
867 /* address space is inaccessible */
868 if (nread) {
869 perror_msg("umoven: short read (%d < %d) @0x%lx",
870 nread, nread + len, addr - nread);
871 }
872 return -1;
873 default:
874 /* all the rest is strange and should be reported */
875 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
876 pid, addr);
877 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700878 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100879 m = MIN(sizeof(long), len);
880 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100881 addr += sizeof(long);
882 laddr += m;
883 nread += m;
884 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887 return 0;
888}
889
890/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100891 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100893 *
894 * Returns < 0 on error, > 0 if NUL was seen,
895 * (TODO if useful: return count of bytes including NUL),
896 * else 0 if len bytes were read but no NUL byte seen.
897 *
898 * Note: there is no guarantee we won't overwrite some bytes
899 * in laddr[] _after_ terminating NUL (but, of course,
900 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 */
902int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000903umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000904{
Denys Vlasenko16940922013-03-01 18:52:59 +0100905#if SIZEOF_LONG == 4
906 const unsigned long x01010101 = 0x01010101ul;
907 const unsigned long x80808080 = 0x80808080ul;
908#elif SIZEOF_LONG == 8
909 const unsigned long x01010101 = 0x0101010101010101ul;
910 const unsigned long x80808080 = 0x8080808080808080ul;
911#else
912# error SIZEOF_LONG > 8
913#endif
914
Roland McGratheb9e2e82009-06-02 16:49:22 -0700915 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100916 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100918 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919 char x[sizeof(long)];
920 } u;
921
Denys Vlasenko2544f982013-02-19 17:39:56 +0100922#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100923 if (current_wordsize < sizeof(addr))
924 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000925#endif
926
Dmitry V. Levin97005922013-02-26 21:16:22 +0000927 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100928 if (!process_vm_readv_not_supported) {
929 struct iovec local[1], remote[1];
930
931 local[0].iov_base = laddr;
932 remote[0].iov_base = (void*)addr;
933
934 while (len > 0) {
935 int end_in_page;
936 int r;
937 int chunk_len;
938
939 /* Don't read kilobytes: most strings are short */
940 chunk_len = len;
941 if (chunk_len > 256)
942 chunk_len = 256;
943 /* Don't cross pages. I guess otherwise we can get EFAULT
944 * and fail to notice that terminating NUL lies
945 * in the existing (first) page.
946 * (I hope there aren't arches with pages < 4K)
947 */
948 end_in_page = ((addr + chunk_len) & 4095);
949 r = chunk_len - end_in_page;
950 if (r > 0) /* if chunk_len > end_in_page */
951 chunk_len = r; /* chunk_len -= end_in_page */
952
953 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000954 r = process_vm_readv(pid, local, 1, remote, 1, 0);
955 if (r > 0) {
956 if (memchr(local[0].iov_base, '\0', r))
957 return 1;
958 local[0].iov_base += r;
959 remote[0].iov_base += r;
960 len -= r;
961 nread += r;
962 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100963 }
Dmitry V. Levin97005922013-02-26 21:16:22 +0000964 switch (errno) {
965 case ENOSYS:
966 process_vm_readv_not_supported = 1;
967 goto vm_readv_didnt_work;
968 case ESRCH:
969 /* the process is gone */
970 return -1;
971 case EFAULT: case EIO: case EPERM:
972 /* address space is inaccessible */
973 if (nread) {
974 perror_msg("umovestr: short read (%d < %d) @0x%lx",
975 nread, nread + len, addr);
976 }
977 return -1;
978 default:
979 /* all the rest is strange and should be reported */
980 perror_msg("process_vm_readv");
981 return -1;
982 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100983 }
984 return 0;
985 }
986 vm_readv_didnt_work:
987
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 if (addr & (sizeof(long) - 1)) {
989 /* addr not a multiple of sizeof(long) */
990 n = addr - (addr & -sizeof(long)); /* residue */
991 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700992 errno = 0;
993 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000994 switch (errno) {
995 case 0:
996 break;
997 case ESRCH: case EINVAL:
998 /* these could be seen if the process is gone */
999 return -1;
1000 case EFAULT: case EIO: case EPERM:
1001 /* address space is inaccessible */
1002 return -1;
1003 default:
1004 /* all the rest is strange and should be reported */
1005 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1006 pid, addr);
1007 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001008 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001009 m = MIN(sizeof(long) - n, len);
1010 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 while (n & (sizeof(long) - 1))
1012 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001013 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001014 addr += sizeof(long);
1015 laddr += m;
1016 nread += m;
1017 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001019
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001021 errno = 0;
1022 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001023 switch (errno) {
1024 case 0:
1025 break;
1026 case ESRCH: case EINVAL:
1027 /* these could be seen if the process is gone */
1028 return -1;
1029 case EFAULT: case EIO: case EPERM:
1030 /* address space is inaccessible */
1031 if (nread) {
1032 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1033 nread, nread + len, addr - nread);
1034 }
1035 return -1;
1036 default:
1037 /* all the rest is strange and should be reported */
1038 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1039 pid, addr);
1040 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001041 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001042 m = MIN(sizeof(long), len);
1043 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001044 /* "If a NUL char exists in this word" */
1045 if ((u.val - x01010101) & ~u.val & x80808080)
1046 return 1;
1047 addr += sizeof(long);
1048 laddr += m;
1049 nread += m;
1050 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001052 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053}
1054
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055int
Denys Vlasenko12014262011-05-30 14:00:14 +02001056upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057{
1058 long val;
1059
Roland McGratheb9e2e82009-06-02 16:49:22 -07001060 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +01001061 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001062 if (val == -1 && errno) {
1063 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001064 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001065 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001067 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 *res = val;
1069 return 0;
1070}
1071
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001072/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1073 * and PTRACE_O_TRACE[V]FORK for tracing children.
1074 * If you are adding a new arch which is only supported by newer kernels,
1075 * you most likely don't need to add any code below
1076 * beside a dummy "return 0" block in change_syscall().
1077 */
1078
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001079/*
1080 * These #if's are huge, please indent them correctly.
1081 * It's easy to get confused otherwise.
1082 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001084#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001085
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001086#ifndef CLONE_PTRACE
1087# define CLONE_PTRACE 0x00002000
1088#endif
1089#ifndef CLONE_VFORK
1090# define CLONE_VFORK 0x00004000
1091#endif
1092#ifndef CLONE_VM
1093# define CLONE_VM 0x00000100
1094#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001095
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001096#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001097
1098typedef unsigned long *arg_setup_state;
1099
1100static int
1101arg_setup(struct tcb *tcp, arg_setup_state *state)
1102{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001103 unsigned long cfm, sof, sol;
1104 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001105
Jan Kratochvil1f942712008-08-06 21:38:52 +00001106 if (ia32) {
1107 /* Satisfy a false GCC warning. */
1108 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001109 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001110 }
Roland McGrath08267b82004-02-20 22:56:43 +00001111
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001112 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001113 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001114 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001115 return -1;
1116
1117 sof = (cfm >> 0) & 0x7f;
1118 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001119 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001120
Jan Kratochvil1f942712008-08-06 21:38:52 +00001121 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001122 return 0;
1123}
1124
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001125# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001126
Roland McGrathd81f1d92003-01-09 06:53:34 +00001127static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001128get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001129{
Roland McGrath08267b82004-02-20 22:56:43 +00001130 int ret;
1131
1132 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001133 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001134 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001135 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001136 (unsigned long) ia64_rse_skip_regs(*state, 0),
1137 sizeof(long), (void *) valp);
1138 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001139}
1140
1141static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001142get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001143{
Roland McGrath08267b82004-02-20 22:56:43 +00001144 int ret;
1145
1146 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001147 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001148 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001149 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001150 (unsigned long) ia64_rse_skip_regs(*state, 1),
1151 sizeof(long), (void *) valp);
1152 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001153}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001154
1155static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001156set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001157{
Roland McGrath08267b82004-02-20 22:56:43 +00001158 int req = PTRACE_POKEDATA;
1159 void *ap;
1160
1161 if (ia32) {
1162 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1163 req = PTRACE_POKEUSER;
1164 } else
1165 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001166 errno = 0;
1167 ptrace(req, tcp->pid, ap, val);
1168 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001169}
1170
1171static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001172set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001173{
Roland McGrath08267b82004-02-20 22:56:43 +00001174 int req = PTRACE_POKEDATA;
1175 void *ap;
1176
1177 if (ia32) {
1178 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1179 req = PTRACE_POKEUSER;
1180 } else
1181 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001182 errno = 0;
1183 ptrace(req, tcp->pid, ap, val);
1184 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001185}
1186
Roland McGrathb659f872008-07-18 01:19:36 +00001187/* ia64 does not return the input arguments from functions (and syscalls)
1188 according to ia64 RSE (Register Stack Engine) behavior. */
1189
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001190# define restore_arg0(tcp, state, val) ((void) (state), 0)
1191# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001192
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001193#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001194
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001195# if defined(SPARC64)
1196# undef PTRACE_GETREGS
1197# define PTRACE_GETREGS PTRACE_GETREGS64
1198# undef PTRACE_SETREGS
1199# define PTRACE_SETREGS PTRACE_SETREGS64
1200# endif
1201
Mike Frysinger8566c502009-10-12 11:05:14 -04001202typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001203
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001204# define arg_setup(tcp, state) \
1205 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1206# define arg_finish_change(tcp, state) \
1207 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001208
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001209# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1210# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1211# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1212# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1213# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001215#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001216
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001217# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001218/* Note: this is only true for the `clone' system call, which handles
1219 arguments specially. We could as well say that its first two arguments
1220 are swapped relative to other architectures, but that would just be
1221 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001222# define arg0_offset PT_GPR3
1223# define arg1_offset PT_ORIGGPR2
1224# define restore_arg0(tcp, state, val) ((void) (state), 0)
1225# define restore_arg1(tcp, state, val) ((void) (state), 0)
1226# define arg0_index 1
1227# define arg1_index 0
1228# elif defined(ALPHA) || defined(MIPS)
1229# define arg0_offset REG_A0
1230# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001231# elif defined(POWERPC)
1232# define arg0_offset (sizeof(unsigned long)*PT_R3)
1233# define arg1_offset (sizeof(unsigned long)*PT_R4)
1234# define restore_arg0(tcp, state, val) ((void) (state), 0)
1235# elif defined(HPPA)
1236# define arg0_offset PT_GR26
1237# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001238# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001239# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1240# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1241# elif defined(SH)
1242# define arg0_offset (4*(REG_REG0+4))
1243# define arg1_offset (4*(REG_REG0+5))
1244# elif defined(SH64)
1245 /* ABI defines arg0 & 1 in r2 & r3 */
1246# define arg0_offset (REG_OFFSET+16)
1247# define arg1_offset (REG_OFFSET+24)
1248# define restore_arg0(tcp, state, val) 0
1249# elif defined CRISV10 || defined CRISV32
1250# define arg0_offset (4*PT_R11)
1251# define arg1_offset (4*PT_ORIG_R10)
1252# define restore_arg0(tcp, state, val) 0
1253# define restore_arg1(tcp, state, val) 0
1254# define arg0_index 1
1255# define arg1_index 0
1256# else
1257# define arg0_offset 0
1258# define arg1_offset 4
1259# if defined ARM
1260# define restore_arg0(tcp, state, val) 0
1261# endif
1262# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263
1264typedef int arg_setup_state;
1265
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001266# define arg_setup(tcp, state) (0)
1267# define arg_finish_change(tcp, state) 0
1268# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1269# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270
1271static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001272set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001274 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275}
1276
1277static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001278set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001280 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281}
1282
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001283#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001285#ifndef restore_arg0
1286# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1287#endif
1288#ifndef restore_arg1
1289# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1290#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001292#ifndef arg0_index
1293# define arg0_index 0
1294# define arg1_index 1
1295#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001296
James Hogan05eb9052012-11-29 17:37:37 +00001297static int
1298change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1299{
1300#if defined(I386)
1301 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1302 return -1;
1303 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001304#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001305 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1306 return -1;
1307 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001308#elif defined(X32)
1309 /* setbpt/clearbpt never used: */
1310 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001311#elif defined(POWERPC)
1312 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1313 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1314 return -1;
1315 return 0;
1316#elif defined(S390) || defined(S390X)
1317 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1318 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1319 return -1;
1320 return 0;
1321#elif defined(M68K)
1322 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1323 return -1;
1324 return 0;
1325#elif defined(SPARC) || defined(SPARC64)
1326 state->u_regs[U_REG_G1] = new;
1327 return 0;
1328#elif defined(MIPS)
1329 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1330 return -1;
1331 return 0;
1332#elif defined(ALPHA)
1333 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1334 return -1;
1335 return 0;
1336#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001337 /* setbpt/clearbpt never used: */
1338 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001339#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001340 /* setbpt/clearbpt never used: */
1341 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001342#elif defined(IA64)
1343 if (ia32) {
1344 switch (new) {
1345 case 2:
1346 break; /* x86 SYS_fork */
1347 case SYS_clone:
1348 new = 120;
1349 break;
1350 default:
1351 fprintf(stderr, "%s: unexpected syscall %d\n",
1352 __FUNCTION__, new);
1353 return -1;
1354 }
1355 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1356 return -1;
1357 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1358 return -1;
1359 return 0;
1360#elif defined(HPPA)
1361 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1362 return -1;
1363 return 0;
1364#elif defined(SH)
1365 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1366 return -1;
1367 return 0;
1368#elif defined(SH64)
1369 /* Top half of reg encodes the no. of args n as 0x1n.
1370 Assume 0 args as kernel never actually checks... */
1371 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1372 0x100000 | new) < 0)
1373 return -1;
1374 return 0;
1375#elif defined(CRISV10) || defined(CRISV32)
1376 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1377 return -1;
1378 return 0;
1379#elif defined(ARM)
1380 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1381# ifndef PTRACE_SET_SYSCALL
1382# define PTRACE_SET_SYSCALL 23
1383# endif
1384 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1385 return -1;
1386 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001387#elif defined(AARCH64)
1388 /* setbpt/clearbpt never used: */
1389 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001390#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001391 /* setbpt/clearbpt never used: */
1392 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001393#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001394 /* setbpt/clearbpt never used: */
1395 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001396#elif defined(OR1K)
1397 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001398#elif defined(METAG)
1399 /* setbpt/clearbpt never used: */
1400 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001401#elif defined(XTENSA)
1402 /* setbpt/clearbpt never used: */
1403 /* Xtensa is only supported since linux 2.6.13 */
James Hogan05eb9052012-11-29 17:37:37 +00001404#else
1405#warning Do not know how to handle change_syscall for this architecture
1406#endif /* architecture */
1407 return -1;
1408}
1409
Roland McGrathd81f1d92003-01-09 06:53:34 +00001410int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001411setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412{
Roland McGrath3291ef22008-05-20 00:34:34 +00001413 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001414 arg_setup_state state;
1415
1416 if (tcp->flags & TCB_BPTSET) {
1417 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1418 return -1;
1419 }
1420
Roland McGrath3291ef22008-05-20 00:34:34 +00001421 /*
1422 * It's a silly kludge to initialize this with a search at runtime.
1423 * But it's better than maintaining another magic thing in the
1424 * godforsaken tables.
1425 */
1426 if (clone_scno[current_personality] == 0) {
1427 int i;
1428 for (i = 0; i < nsyscalls; ++i)
1429 if (sysent[i].sys_func == sys_clone) {
1430 clone_scno[current_personality] = i;
1431 break;
1432 }
1433 }
1434
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001435 if (tcp->s_ent->sys_func == sys_fork ||
1436 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001437 if (arg_setup(tcp, &state) < 0
1438 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1439 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001440 || change_syscall(tcp, &state,
1441 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001442 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1443 || set_arg1(tcp, &state, 0) < 0
1444 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001445 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001446 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1447 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001448 tcp->flags |= TCB_BPTSET;
1449 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001450 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001451
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001452 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001453 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001454 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001455 vfork semantics into plain fork - each application must not
1456 depend on the vfork specifics according to POSIX. We would
1457 hang waiting for the parent resume otherwise. We need to
1458 clear also CLONE_VM but only in the CLONE_VFORK case as
1459 otherwise we would break pthread_create. */
1460
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001461 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1462 if (new_arg0 & CLONE_VFORK)
1463 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1464 if (arg_setup(tcp, &state) < 0
1465 || set_arg0(tcp, &state, new_arg0) < 0
1466 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001467 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001468 tcp->inst[0] = tcp->u_arg[arg0_index];
1469 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001470 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001471 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001472 }
1473
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001474 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1475 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001476 return -1;
1477}
1478
1479int
Denys Vlasenko12014262011-05-30 14:00:14 +02001480clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481{
1482 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001483 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001484 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001485 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1486 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1487 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001488 if (errno != ESRCH)
1489 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001490 tcp->flags &= ~TCB_BPTSET;
1491 return 0;
1492}