blob: e57f46ae3045b0aa8b5ca525e11b0025518a8c5d [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 __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010043# include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000044#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000045
Denys Vlasenko84703742012-02-25 02:38:52 +010046#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000047# include <asm/ptrace_offsets.h>
48# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000049#endif
50
Wichert Akkerman36915a11999-07-13 15:45:02 +000051#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010052# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000053# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000054#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010055# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000056# ifdef HAVE_STRUCT_IA64_FPREG
57# define ia64_fpreg XXX_ia64_fpreg
58# endif
59# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
60# define pt_all_user_regs XXX_pt_all_user_regs
61# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010062# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000063# undef ia64_fpreg
64# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000065#endif
66
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010067#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000068# undef PTRACE_GETREGS
69# define PTRACE_GETREGS PTRACE_GETREGS64
70# undef PTRACE_SETREGS
71# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000072#endif
73
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074/* macros */
75#ifndef MAX
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010076# define MAX(a,b) (((a) > (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
78#ifndef MIN
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010079# define MIN(a,b) (((a) < (b)) ? (a) : (b))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#endif
81
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082int
Denys Vlasenko12014262011-05-30 14:00:14 +020083tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084{
85 return a->tv_sec || a->tv_usec;
86}
87
88int
Denys Vlasenko12014262011-05-30 14:00:14 +020089tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090{
91 if (a->tv_sec < b->tv_sec
92 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
93 return -1;
94 if (a->tv_sec > b->tv_sec
95 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
96 return 1;
97 return 0;
98}
99
100double
Denys Vlasenko12014262011-05-30 14:00:14 +0200101tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102{
103 return tv->tv_sec + tv->tv_usec/1000000.0;
104}
105
106void
Denys Vlasenko12014262011-05-30 14:00:14 +0200107tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 tv->tv_sec = a->tv_sec + b->tv_sec;
110 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000111 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112 tv->tv_sec++;
113 tv->tv_usec -= 1000000;
114 }
115}
116
117void
Denys Vlasenko12014262011-05-30 14:00:14 +0200118tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119{
120 tv->tv_sec = a->tv_sec - b->tv_sec;
121 tv->tv_usec = a->tv_usec - b->tv_usec;
122 if (((long) tv->tv_usec) < 0) {
123 tv->tv_sec--;
124 tv->tv_usec += 1000000;
125 }
126}
127
128void
Denys Vlasenko12014262011-05-30 14:00:14 +0200129tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130{
131 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
132 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
133 tv->tv_usec %= 1000000;
134}
135
136void
Denys Vlasenko12014262011-05-30 14:00:14 +0200137tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138{
139 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000140 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141 tv->tv_usec %= 1000000;
142}
143
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000144const char *
145xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146{
147 for (; xlat->str != NULL; xlat++)
148 if (xlat->val == val)
149 return xlat->str;
150 return NULL;
151}
152
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200153#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200154char *
155stpcpy(char *dst, const char *src)
156{
157 while ((*dst = *src++) != '\0')
158 dst++;
159 return dst;
160}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200161#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163/*
164 * Print entry in struct xlat table, if there.
165 */
166void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000167printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000169 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
171 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200172 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173 else
174 tprintf("%#x /* %s */", val, dflt);
175}
176
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100177#if HAVE_LONG_LONG
178/*
179 * Print 64bit argument at position llarg and return the index of the next
180 * argument.
181 */
182int
183printllval(struct tcb *tcp, const char *format, int llarg)
184{
Denys Vlasenkoaa925db2012-02-25 15:19:02 +0100185# if defined(X86_64) || defined(POWERPC64)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100186 if (current_personality == 0) {
187 tprintf(format, tcp->u_arg[llarg]);
188 llarg++;
189 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200190# ifdef POWERPC64
191 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200192 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200193# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100194 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
195 llarg += 2;
196 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200197# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100198 tprintf(format, tcp->u_arg[llarg]);
199 llarg++;
200# elif defined LINUX_MIPSN32
201 tprintf(format, tcp->ext_arg[llarg]);
202 llarg++;
203# else
204 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
205 llarg += 2;
206# endif
207 return llarg;
208}
209#endif
210
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211/*
212 * Interpret `xlat' as an array of flags
213 * print the entries whose bits are on in `flags'
214 * return # of flags printed.
215 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200216void
Denys Vlasenko12014262011-05-30 14:00:14 +0200217addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000218{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200219 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000220 if (xlat->val && (flags & xlat->val) == xlat->val) {
221 tprintf("|%s", xlat->str);
222 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 }
224 }
225 if (flags) {
226 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228}
229
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000230/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200231 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000232 * Print to static string the entries whose bits are on in `flags'
233 * Return static string.
234 */
235const char *
236sprintflags(const char *prefix, const struct xlat *xlat, int flags)
237{
238 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200239 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000240 int found = 0;
241
Denys Vlasenko52845572011-08-31 12:07:38 +0200242 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000243
244 for (; xlat->str; xlat++) {
245 if ((flags & xlat->val) == xlat->val) {
246 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200247 *outptr++ = '|';
248 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000249 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100250 flags &= ~xlat->val;
251 if (!flags)
252 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000253 }
254 }
255 if (flags) {
256 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200257 *outptr++ = '|';
258 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000259 }
260
261 return outstr;
262}
263
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000264int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000265printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000266{
267 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000268 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269
270 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200271 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272 return 1;
273 }
274
275 sep = "";
276 for (n = 0; xlat->str; xlat++) {
277 if (xlat->val && (flags & xlat->val) == xlat->val) {
278 tprintf("%s%s", sep, xlat->str);
279 flags &= ~xlat->val;
280 sep = "|";
281 n++;
282 }
283 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000284
285 if (n) {
286 if (flags) {
287 tprintf("%s%#x", sep, flags);
288 n++;
289 }
290 } else {
291 if (flags) {
292 tprintf("%#x", flags);
293 if (dflt)
294 tprintf(" /* %s */", dflt);
295 } else {
296 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200297 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000298 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000300
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301 return n;
302}
303
304void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000305printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000306{
Roland McGratheb285352003-01-14 09:59:00 +0000307 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308
309 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200310 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 return;
312 }
313 if (umove(tcp, addr, &num) < 0) {
314 tprintf("%#lx", addr);
315 return;
316 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200317 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200319 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000320}
321
Roland McGrath6bc12202003-11-13 22:32:27 +0000322void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000323printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000324{
325 int num;
326
327 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200328 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000329 return;
330 }
331 if (umove(tcp, addr, &num) < 0) {
332 tprintf("%#lx", addr);
333 return;
334 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200335 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000336 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200337 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000338}
339
340void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300341printfd(struct tcb *tcp, int fd)
342{
Grant Edwards8a082772011-04-07 20:25:40 +0000343 const char *p;
344
345 if (show_fd_path && (p = getfdpath(tcp, fd)))
346 tprintf("%d<%s>", fd, p);
347 else
348 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300349}
350
351void
Denys Vlasenko12014262011-05-30 14:00:14 +0200352printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000353{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200354 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000355}
356
Dmitry V. Levina501f142008-11-10 23:19:13 +0000357/*
358 * Quote string `instr' of length `size'
359 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
360 * If `len' < 0, treat `instr' as a NUL-terminated string
361 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100362 *
363 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
364 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000365 */
Roland McGrath6d970322007-11-01 23:53:59 +0000366static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000367string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000368{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000369 const unsigned char *ustr = (const unsigned char *) instr;
370 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200371 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200373 eol = 0x100; /* this can never match a char */
374 if (len < 0) {
375 size--;
376 eol = '\0';
377 }
378
379 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000380 if (xflag > 1)
381 usehex = 1;
382 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000383 /* Check for presence of symbol which require
384 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000385 for (i = 0; i < size; ++i) {
386 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000387 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200388 if (c == eol)
389 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000390 if (!isprint(c) && !isspace(c)) {
391 usehex = 1;
392 break;
393 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 }
395 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000396
397 *s++ = '\"';
398
399 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000400 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000401 for (i = 0; i < size; ++i) {
402 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000403 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200404 if (c == eol)
405 goto asciz_ended;
406 *s++ = '\\';
407 *s++ = 'x';
408 *s++ = "0123456789abcdef"[c >> 4];
409 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000410 }
411 } else {
412 for (i = 0; i < size; ++i) {
413 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000414 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200415 if (c == eol)
416 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000417 switch (c) {
418 case '\"': case '\\':
419 *s++ = '\\';
420 *s++ = c;
421 break;
422 case '\f':
423 *s++ = '\\';
424 *s++ = 'f';
425 break;
426 case '\n':
427 *s++ = '\\';
428 *s++ = 'n';
429 break;
430 case '\r':
431 *s++ = '\\';
432 *s++ = 'r';
433 break;
434 case '\t':
435 *s++ = '\\';
436 *s++ = 't';
437 break;
438 case '\v':
439 *s++ = '\\';
440 *s++ = 'v';
441 break;
442 default:
443 if (isprint(c))
444 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200445 else {
446 /* Print \octal */
447 *s++ = '\\';
448 if (i + 1 < size
449 && ustr[i + 1] >= '0'
450 && ustr[i + 1] <= '9'
451 ) {
452 /* Print \ooo */
453 *s++ = '0' + (c >> 6);
454 *s++ = '0' + ((c >> 3) & 0x7);
455 } else {
456 /* Print \[[o]o]o */
457 if ((c >> 3) != 0) {
458 if ((c >> 6) != 0)
459 *s++ = '0' + (c >> 6);
460 *s++ = '0' + ((c >> 3) & 0x7);
461 }
462 }
463 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000464 }
465 break;
466 }
467 }
468 }
469
470 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000472
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200473 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
474 if (len < 0 && ustr[i] == '\0') {
475 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
476 * but next char is NUL.
477 */
478 return 0;
479 }
480
481 return 1;
482
483 asciz_ended:
484 *s++ = '\"';
485 *s = '\0';
486 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
487 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488}
489
Dmitry V. Levina501f142008-11-10 23:19:13 +0000490/*
491 * Print path string specified by address `addr' and length `n'.
492 * If path length exceeds `n', append `...' to the output.
493 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000494void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000495printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000496{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100497 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100498 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100499
Dmitry V. Levina501f142008-11-10 23:19:13 +0000500 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200501 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000502 return;
503 }
504
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100505 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000506 if (n > sizeof path - 1)
507 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000508
509 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100510 nul_seen = umovestr(tcp, addr, n + 1, path);
511 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 tprintf("%#lx", addr);
513 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100514 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000515
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100516 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100517 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100518 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100519 string_quote(path, outstr, -1, n);
520 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100521 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100522 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523 }
524}
525
526void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000527printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100529 /* Size must correspond to char path[] size in printpathn */
530 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000531}
532
Dmitry V. Levina501f142008-11-10 23:19:13 +0000533/*
534 * Print string specified by address `addr' and length `len'.
535 * If `len' < 0, treat the string as a NUL-terminated string.
536 * If string length exceeds `max_strlen', append `...' to the output.
537 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000538void
539printstr(struct tcb *tcp, long addr, int len)
540{
541 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000543 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100544 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545
546 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200547 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 return;
549 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000550 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200551 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000552 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200553 if (!str)
554 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100555 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200556 if (!outstr)
557 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000559
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000561 /*
562 * Treat as a NUL-terminated string: fetch one byte more
563 * because string_quote() quotes one byte less.
564 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 size = max_strlen + 1;
566 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 tprintf("%#lx", addr);
568 return;
569 }
570 }
571 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000572 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000573 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 tprintf("%#lx", addr);
575 return;
576 }
577 }
578
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100579 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
580 * or we were requested to print more than -s NUM chars)...
581 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100582 ellipsis = (string_quote(str, outstr, len, size) &&
583 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000584
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100585 tprints(outstr);
586 if (ellipsis)
587 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588}
589
John Hughes1d08dcf2001-07-10 13:48:44 +0000590#if HAVE_SYS_UIO_H
591void
Denys Vlasenko12014262011-05-30 14:00:14 +0200592dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000593{
Denys Vlasenko84703742012-02-25 02:38:52 +0100594#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000595 union {
596 struct { u_int32_t base; u_int32_t len; } *iov32;
597 struct { u_int64_t base; u_int64_t len; } *iov64;
598 } iovu;
599#define iov iovu.iov64
600#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100601 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000602#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100603 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000604#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100605 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000606#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000607 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000608#define sizeof_iov sizeof(*iov)
609#define iov_iov_base(i) iov[i].iov_base
610#define iov_iov_len(i) iov[i].iov_len
611#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000612 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200613 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000614
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200615 size = sizeof_iov * len;
616 /* Assuming no sane program has millions of iovs */
617 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000618 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200619 fprintf(stderr, "Out of memory\n");
620 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000621 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000622 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000623 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000624 /* include the buffer number to make it easy to
625 * match up the trace with the source */
626 tprintf(" * %lu bytes in buffer %d\n",
627 (unsigned long)iov_iov_len(i), i);
628 dumpstr(tcp, (long) iov_iov_base(i),
629 iov_iov_len(i));
630 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000631 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200632 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000633#undef sizeof_iov
634#undef iov_iov_base
635#undef iov_iov_len
636#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000637}
638#endif
639
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640void
Denys Vlasenko12014262011-05-30 14:00:14 +0200641dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000642{
643 static int strsize = -1;
644 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645 char *s;
646 int i, j;
647
648 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200649 free(str);
650 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200651 if (!str) {
652 strsize = -1;
653 fprintf(stderr, "Out of memory\n");
654 return;
655 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656 strsize = len;
657 }
658
659 if (umoven(tcp, addr, len, (char *) str) < 0)
660 return;
661
662 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200663 char outstr[80];
664
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665 s = outstr;
666 sprintf(s, " | %05x ", i);
667 s += 9;
668 for (j = 0; j < 16; j++) {
669 if (j == 8)
670 *s++ = ' ';
671 if (i + j < len) {
672 sprintf(s, " %02x", str[i + j]);
673 s += 3;
674 }
675 else {
676 *s++ = ' '; *s++ = ' '; *s++ = ' ';
677 }
678 }
679 *s++ = ' '; *s++ = ' ';
680 for (j = 0; j < 16; j++) {
681 if (j == 8)
682 *s++ = ' ';
683 if (i + j < len) {
684 if (isprint(str[i + j]))
685 *s++ = str[i + j];
686 else
687 *s++ = '.';
688 }
689 else
690 *s++ = ' ';
691 }
692 tprintf("%s |\n", outstr);
693 }
694}
695
Mike Frysinger612659e2012-02-14 14:38:28 +0100696#ifdef HAVE_PROCESS_VM_READV
697/* C library supports this, but the kernel might not. */
698static bool process_vm_readv_not_supported = 0;
699#else
700
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100701/* Need to do this since process_vm_readv() is not yet available in libc.
702 * When libc is be updated, only "static bool process_vm_readv_not_supported"
703 * line should remain.
704 */
705#if !defined(__NR_process_vm_readv)
706# if defined(I386)
707# define __NR_process_vm_readv 347
708# elif defined(X86_64)
709# define __NR_process_vm_readv 310
710# elif defined(POWERPC)
711# define __NR_process_vm_readv 351
712# endif
713#endif
714
715#if defined(__NR_process_vm_readv)
716static bool process_vm_readv_not_supported = 0;
717static ssize_t process_vm_readv(pid_t pid,
718 const struct iovec *lvec,
719 unsigned long liovcnt,
720 const struct iovec *rvec,
721 unsigned long riovcnt,
722 unsigned long flags)
723{
724 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
725}
726#else
727static bool process_vm_readv_not_supported = 1;
728# define process_vm_readv(...) (errno = ENOSYS, -1)
729#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100730
731#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100732
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733#define PAGMASK (~(PAGSIZ - 1))
734/*
735 * move `len' bytes of data from process `pid'
736 * at address `addr' to our space at `laddr'
737 */
738int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000739umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000740{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700741 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100743 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744 union {
745 long val;
746 char x[sizeof(long)];
747 } u;
748
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100749#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100750 if (current_wordsize < sizeof(addr))
751 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100752#endif
753
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100754 if (!process_vm_readv_not_supported) {
755 struct iovec local[1], remote[1];
756 int r;
757
758 local[0].iov_base = laddr;
759 remote[0].iov_base = (void*)addr;
760 local[0].iov_len = remote[0].iov_len = len;
761 r = process_vm_readv(pid,
762 local, 1,
763 remote, 1,
764 /*flags:*/ 0
765 );
766 if (r < 0) {
767 if (errno == ENOSYS)
768 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100769 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
770 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100771 perror("process_vm_readv");
772 goto vm_readv_didnt_work;
773 }
774 return r;
775 }
776 vm_readv_didnt_work:
777
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100778 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 if (addr & (sizeof(long) - 1)) {
780 /* addr not a multiple of sizeof(long) */
781 n = addr - (addr & -sizeof(long)); /* residue */
782 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700783 errno = 0;
784 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
785 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700786 /* But if not started, we had a bogus address. */
787 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100788 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700789 return -1;
790 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000791 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100792 m = MIN(sizeof(long) - n, len);
793 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 addr += sizeof(long), laddr += m, len -= m;
795 }
796 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700797 errno = 0;
798 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
799 if (errno) {
800 if (started && (errno==EPERM || errno==EIO)) {
801 /* Ran into 'end of memory' - stupid "printpath" */
802 return 0;
803 }
804 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100805 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700806 return -1;
807 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000808 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100809 m = MIN(sizeof(long), len);
810 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 addr += sizeof(long), laddr += m, len -= m;
812 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 return 0;
815}
816
817/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100818 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100820 *
821 * Returns < 0 on error, > 0 if NUL was seen,
822 * (TODO if useful: return count of bytes including NUL),
823 * else 0 if len bytes were read but no NUL byte seen.
824 *
825 * Note: there is no guarantee we won't overwrite some bytes
826 * in laddr[] _after_ terminating NUL (but, of course,
827 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 */
829int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000830umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100832 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700833 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834 int i, n, m;
835 union {
836 long val;
837 char x[sizeof(long)];
838 } u;
839
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000840#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100841 if (current_wordsize < sizeof(addr))
842 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000843#endif
844
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100845 if (!process_vm_readv_not_supported) {
846 struct iovec local[1], remote[1];
847
848 local[0].iov_base = laddr;
849 remote[0].iov_base = (void*)addr;
850
851 while (len > 0) {
852 int end_in_page;
853 int r;
854 int chunk_len;
855
856 /* Don't read kilobytes: most strings are short */
857 chunk_len = len;
858 if (chunk_len > 256)
859 chunk_len = 256;
860 /* Don't cross pages. I guess otherwise we can get EFAULT
861 * and fail to notice that terminating NUL lies
862 * in the existing (first) page.
863 * (I hope there aren't arches with pages < 4K)
864 */
865 end_in_page = ((addr + chunk_len) & 4095);
866 r = chunk_len - end_in_page;
867 if (r > 0) /* if chunk_len > end_in_page */
868 chunk_len = r; /* chunk_len -= end_in_page */
869
870 local[0].iov_len = remote[0].iov_len = chunk_len;
871 r = process_vm_readv(pid,
872 local, 1,
873 remote, 1,
874 /*flags:*/ 0
875 );
876 if (r < 0) {
877 if (errno == ENOSYS)
878 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100879 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
880 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100881 perror("process_vm_readv");
882 goto vm_readv_didnt_work;
883 }
884 if (memchr(local[0].iov_base, '\0', r))
885 return 1;
886 local[0].iov_base += r;
887 remote[0].iov_base += r;
888 len -= r;
889 }
890 return 0;
891 }
892 vm_readv_didnt_work:
893
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100894 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 if (addr & (sizeof(long) - 1)) {
896 /* addr not a multiple of sizeof(long) */
897 n = addr - (addr & -sizeof(long)); /* residue */
898 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700899 errno = 0;
900 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
901 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700902 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100903 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700904 return -1;
905 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000906 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100907 m = MIN(sizeof(long) - n, len);
908 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 while (n & (sizeof(long) - 1))
910 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100911 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 addr += sizeof(long), laddr += m, len -= m;
913 }
914 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700915 errno = 0;
916 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
917 if (errno) {
918 if (started && (errno==EPERM || errno==EIO)) {
919 /* Ran into 'end of memory' - stupid "printpath" */
920 return 0;
921 }
922 if (addr != 0 && errno != EIO && errno != ESRCH)
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100923 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx", pid, addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700924 return -1;
925 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000926 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100927 m = MIN(sizeof(long), len);
928 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000929 for (i = 0; i < sizeof(long); i++)
930 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100931 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932 addr += sizeof(long), laddr += m, len -= m;
933 }
John Hughesaa09c6b2001-05-15 14:53:43 +0000934 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935}
936
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937int
Denys Vlasenko12014262011-05-30 14:00:14 +0200938upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939{
940 long val;
941
Roland McGratheb9e2e82009-06-02 16:49:22 -0700942 errno = 0;
Denys Vlasenko114aefd2012-03-08 12:13:44 +0100943 val = ptrace(PTRACE_PEEKUSER, tcp->pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700944 if (val == -1 && errno) {
945 if (errno != ESRCH) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100946 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700947 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700949 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950 *res = val;
951 return 0;
952}
953
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000955printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956{
Roland McGrath7a918832005-02-02 20:55:23 +0000957#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
958 sizeof(long) == 8 ? "[????????????????] " : \
959 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100961#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962 long eip;
963
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000964 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +0000965 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 return;
967 }
968 tprintf("[%08lx] ", eip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100969#elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000970 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200971 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000972 PRINTBADPC;
973 return;
974 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100975# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000976 tprintf("[%08lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100977# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000978 tprintf("[%16lx] ", psw);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100979# endif
Roland McGratheac26fc2005-02-02 02:48:53 +0000980
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100981#elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +0000982 long rip;
983
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000984 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +0000985 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +0000986 return;
987 }
988 tprintf("[%16lx] ", rip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100989#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000990 long ip;
991
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000992 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +0000993 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000994 return;
995 }
996 tprintf("[%08lx] ", ip);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +0100997#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 long pc;
999
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001000 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001001 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 return;
1003 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001004# ifdef POWERPC64
Andreas Schwabd69fa492010-07-12 21:39:57 +02001005 tprintf("[%016lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001006# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001008# endif
1009#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 long pc;
1011
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001012 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001013 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 return;
1015 }
1016 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001017#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 long pc;
1019
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001020 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001021 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 return;
1023 }
1024 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001025#elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001026 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001027 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001028 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 return;
1030 }
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001031# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001032 tprintf("[%08lx] ", regs.tpc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001033# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001034 tprintf("[%08lx] ", regs.pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001035# endif
1036#elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001037 long pc;
1038
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001039 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001040 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001041 return;
1042 }
1043 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001044#elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001045 long pc;
1046
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001047 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001048 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001049 return;
1050 }
1051 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001052#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001053 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001054
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001055 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001056 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001057 return;
1058 }
1059 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001060#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001061 long pc;
1062
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001063 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001064 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001065 return;
1066 }
1067 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001068#elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001069 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001070
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001071 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001072 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001073 return;
1074 }
1075 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001076#elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001077 long pc;
1078
1079 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001080 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001081 return;
1082 }
1083 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001084#elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001085 long pc;
1086
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001087 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001088 PRINTBADPC;
1089 return;
1090 }
1091 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001092#elif defined(CRISV10)
1093 long pc;
1094
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001095 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001096 PRINTBADPC;
1097 return;
1098 }
1099 tprintf("[%08lx] ", pc);
1100#elif defined(CRISV32)
1101 long pc;
1102
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001103 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001104 PRINTBADPC;
1105 return;
1106 }
1107 tprintf("[%08lx] ", pc);
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001108#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109}
1110
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001111/*
1112 * These #if's are huge, please indent them correctly.
1113 * It's easy to get confused otherwise.
1114 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001116#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001117
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001118#ifndef CLONE_PTRACE
1119# define CLONE_PTRACE 0x00002000
1120#endif
1121#ifndef CLONE_VFORK
1122# define CLONE_VFORK 0x00004000
1123#endif
1124#ifndef CLONE_VM
1125# define CLONE_VM 0x00000100
1126#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001127
Denys Vlasenko081533c2012-03-17 02:17:51 +01001128static int
1129change_syscall(struct tcb *tcp, int new)
1130{
1131#if defined(I386)
1132 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1133 return -1;
1134 return 0;
1135#elif defined(X86_64)
1136 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1137 return -1;
1138 return 0;
1139#elif defined(POWERPC)
1140 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1141 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1142 return -1;
1143 return 0;
1144#elif defined(S390) || defined(S390X)
1145 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1146 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1147 return -1;
1148 return 0;
1149#elif defined(M68K)
1150 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1151 return -1;
1152 return 0;
1153#elif defined(SPARC) || defined(SPARC64)
1154 struct pt_regs regs;
1155 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0) < 0)
1156 return -1;
1157 regs.u_regs[U_REG_G1] = new;
1158 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0) < 0)
1159 return -1;
1160 return 0;
1161#elif defined(MIPS)
1162 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1163 return -1;
1164 return 0;
1165#elif defined(ALPHA)
1166 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1167 return -1;
1168 return 0;
1169#elif defined(AVR32)
1170 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R8), new) < 0)
1171 return -1;
1172 return 0;
1173#elif defined(BFIN)
1174 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_P0), new) < 0)
1175 return -1;
1176 return 0;
1177#elif defined(IA64)
1178 if (ia32) {
1179 switch (new) {
1180 case 2:
1181 break; /* x86 SYS_fork */
1182 case SYS_clone:
1183 new = 120;
1184 break;
1185 default:
1186 fprintf(stderr, "%s: unexpected syscall %d\n",
1187 __FUNCTION__, new);
1188 return -1;
1189 }
1190 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1191 return -1;
1192 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1193 return -1;
1194 return 0;
1195#elif defined(HPPA)
1196 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1197 return -1;
1198 return 0;
1199#elif defined(SH)
1200 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1201 return -1;
1202 return 0;
1203#elif defined(SH64)
1204 /* Top half of reg encodes the no. of args n as 0x1n.
1205 Assume 0 args as kernel never actually checks... */
1206 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1207 0x100000 | new) < 0)
1208 return -1;
1209 return 0;
1210#elif defined(CRISV10) || defined(CRISV32)
1211 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1212 return -1;
1213 return 0;
1214#elif defined(ARM)
1215 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1216# ifndef PTRACE_SET_SYSCALL
1217# define PTRACE_SET_SYSCALL 23
1218# endif
1219 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1220 return -1;
1221 return 0;
1222#elif defined(TILE)
1223 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1224 (char*)PTREGS_OFFSET_REG(0),
1225 new) != 0)
1226 return -1;
1227 return 0;
1228#elif defined(MICROBLAZE)
1229 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR(0)), new) < 0)
1230 return -1;
1231 return 0;
1232#else
1233#warning Do not know how to handle change_syscall for this architecture
1234#endif /* architecture */
1235 return -1;
1236}
1237
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001238#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001239
1240typedef unsigned long *arg_setup_state;
1241
1242static int
1243arg_setup(struct tcb *tcp, arg_setup_state *state)
1244{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001245 unsigned long cfm, sof, sol;
1246 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001247
Jan Kratochvil1f942712008-08-06 21:38:52 +00001248 if (ia32) {
1249 /* Satisfy a false GCC warning. */
1250 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001251 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001252 }
Roland McGrath08267b82004-02-20 22:56:43 +00001253
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001254 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001255 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001256 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257 return -1;
1258
1259 sof = (cfm >> 0) & 0x7f;
1260 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001261 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262
Jan Kratochvil1f942712008-08-06 21:38:52 +00001263 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001264 return 0;
1265}
1266
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001267# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001270get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271{
Roland McGrath08267b82004-02-20 22:56:43 +00001272 int ret;
1273
1274 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001275 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001276 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001277 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001278 (unsigned long) ia64_rse_skip_regs(*state, 0),
1279 sizeof(long), (void *) valp);
1280 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281}
1282
1283static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001284get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001285{
Roland McGrath08267b82004-02-20 22:56:43 +00001286 int ret;
1287
1288 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001289 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001290 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001291 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001292 (unsigned long) ia64_rse_skip_regs(*state, 1),
1293 sizeof(long), (void *) valp);
1294 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296
1297static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001298set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299{
Roland McGrath08267b82004-02-20 22:56:43 +00001300 int req = PTRACE_POKEDATA;
1301 void *ap;
1302
1303 if (ia32) {
1304 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1305 req = PTRACE_POKEUSER;
1306 } else
1307 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001308 errno = 0;
1309 ptrace(req, tcp->pid, ap, val);
1310 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311}
1312
1313static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001314set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001315{
Roland McGrath08267b82004-02-20 22:56:43 +00001316 int req = PTRACE_POKEDATA;
1317 void *ap;
1318
1319 if (ia32) {
1320 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1321 req = PTRACE_POKEUSER;
1322 } else
1323 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001324 errno = 0;
1325 ptrace(req, tcp->pid, ap, val);
1326 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327}
1328
Roland McGrathb659f872008-07-18 01:19:36 +00001329/* ia64 does not return the input arguments from functions (and syscalls)
1330 according to ia64 RSE (Register Stack Engine) behavior. */
1331
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001332# define restore_arg0(tcp, state, val) ((void) (state), 0)
1333# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001334
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001335#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336
Mike Frysinger8566c502009-10-12 11:05:14 -04001337typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001339# define arg_setup(tcp, state) \
1340 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1341# define arg_finish_change(tcp, state) \
1342 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001343
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001344# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1345# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1346# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1347# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1348# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001350#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001352# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001353/* Note: this is only true for the `clone' system call, which handles
1354 arguments specially. We could as well say that its first two arguments
1355 are swapped relative to other architectures, but that would just be
1356 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001357# define arg0_offset PT_GPR3
1358# define arg1_offset PT_ORIGGPR2
1359# define restore_arg0(tcp, state, val) ((void) (state), 0)
1360# define restore_arg1(tcp, state, val) ((void) (state), 0)
1361# define arg0_index 1
1362# define arg1_index 0
1363# elif defined(ALPHA) || defined(MIPS)
1364# define arg0_offset REG_A0
1365# define arg1_offset (REG_A0+1)
1366# elif defined(AVR32)
1367# define arg0_offset (REG_R12)
1368# define arg1_offset (REG_R11)
1369# elif defined(POWERPC)
1370# define arg0_offset (sizeof(unsigned long)*PT_R3)
1371# define arg1_offset (sizeof(unsigned long)*PT_R4)
1372# define restore_arg0(tcp, state, val) ((void) (state), 0)
1373# elif defined(HPPA)
1374# define arg0_offset PT_GR26
1375# define arg1_offset (PT_GR26-4)
1376# elif defined(X86_64)
1377# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1378# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1379# elif defined(SH)
1380# define arg0_offset (4*(REG_REG0+4))
1381# define arg1_offset (4*(REG_REG0+5))
1382# elif defined(SH64)
1383 /* ABI defines arg0 & 1 in r2 & r3 */
1384# define arg0_offset (REG_OFFSET+16)
1385# define arg1_offset (REG_OFFSET+24)
1386# define restore_arg0(tcp, state, val) 0
1387# elif defined CRISV10 || defined CRISV32
1388# define arg0_offset (4*PT_R11)
1389# define arg1_offset (4*PT_ORIG_R10)
1390# define restore_arg0(tcp, state, val) 0
1391# define restore_arg1(tcp, state, val) 0
1392# define arg0_index 1
1393# define arg1_index 0
1394# else
1395# define arg0_offset 0
1396# define arg1_offset 4
1397# if defined ARM
1398# define restore_arg0(tcp, state, val) 0
1399# endif
1400# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401
1402typedef int arg_setup_state;
1403
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001404# define arg_setup(tcp, state) (0)
1405# define arg_finish_change(tcp, state) 0
1406# define get_arg0(tcp, cookie, valp) (upeek((tcp), arg0_offset, (valp)))
1407# define get_arg1(tcp, cookie, valp) (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001408
1409static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001410set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001412 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413}
1414
1415static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001416set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001418 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001419}
1420
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001421#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001423#ifndef restore_arg0
1424# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1425#endif
1426#ifndef restore_arg1
1427# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1428#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001429
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001430#ifndef arg0_index
1431# define arg0_index 0
1432# define arg1_index 1
1433#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001434
Roland McGrathd81f1d92003-01-09 06:53:34 +00001435int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001436setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437{
Roland McGrath3291ef22008-05-20 00:34:34 +00001438 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001439 arg_setup_state state;
1440
1441 if (tcp->flags & TCB_BPTSET) {
1442 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1443 return -1;
1444 }
1445
Roland McGrath3291ef22008-05-20 00:34:34 +00001446 /*
1447 * It's a silly kludge to initialize this with a search at runtime.
1448 * But it's better than maintaining another magic thing in the
1449 * godforsaken tables.
1450 */
1451 if (clone_scno[current_personality] == 0) {
1452 int i;
1453 for (i = 0; i < nsyscalls; ++i)
1454 if (sysent[i].sys_func == sys_clone) {
1455 clone_scno[current_personality] = i;
1456 break;
1457 }
1458 }
1459
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001460 if (sysent[tcp->scno].sys_func == sys_fork ||
1461 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001462 if (arg_setup(tcp, &state) < 0
1463 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1464 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001465 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001466 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1467 || set_arg1(tcp, &state, 0) < 0
1468 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001469 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001470 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1471 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001472 tcp->flags |= TCB_BPTSET;
1473 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001474 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001475
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001476 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001477 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001478 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001479 vfork semantics into plain fork - each application must not
1480 depend on the vfork specifics according to POSIX. We would
1481 hang waiting for the parent resume otherwise. We need to
1482 clear also CLONE_VM but only in the CLONE_VFORK case as
1483 otherwise we would break pthread_create. */
1484
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001485 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1486 if (new_arg0 & CLONE_VFORK)
1487 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1488 if (arg_setup(tcp, &state) < 0
1489 || set_arg0(tcp, &state, new_arg0) < 0
1490 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001491 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001492 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001493 tcp->inst[0] = tcp->u_arg[arg0_index];
1494 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001495 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001496 }
1497
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001498 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1499 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001500 return -1;
1501}
1502
1503int
Denys Vlasenko12014262011-05-30 14:00:14 +02001504clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001505{
1506 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001507 if (arg_setup(tcp, &state) < 0
1508 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1509 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1510 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001511 if (errno != ESRCH)
1512 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001513 tcp->flags &= ~TCB_BPTSET;
1514 return 0;
1515}