blob: 80acc133f818f49cae247b5e283115b35250602f [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.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000046
Denys Vlasenko84703742012-02-25 02:38:52 +010047#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000049#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000050
Denys Vlasenko84703742012-02-25 02:38:52 +010051#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000052# include <asm/ptrace_offsets.h>
53# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000054#endif
55
Wichert Akkerman36915a11999-07-13 15:45:02 +000056#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010057# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000058# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000059#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010060# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000061# ifdef HAVE_STRUCT_IA64_FPREG
62# define ia64_fpreg XXX_ia64_fpreg
63# endif
64# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
65# define pt_all_user_regs XXX_pt_all_user_regs
66# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010067# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000068# undef ia64_fpreg
69# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000070#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072
Mike Frysinger8566c502009-10-12 11:05:14 -040073#if defined(LINUXSPARC) && defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000074# undef PTRACE_GETREGS
75# define PTRACE_GETREGS PTRACE_GETREGS64
76# undef PTRACE_SETREGS
77# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000078#endif
79
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080/* macros */
81#ifndef MAX
82#define MAX(a,b) (((a) > (b)) ? (a) : (b))
83#endif
84#ifndef MIN
85#define MIN(a,b) (((a) < (b)) ? (a) : (b))
86#endif
87
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088int
Denys Vlasenko12014262011-05-30 14:00:14 +020089tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090{
91 return a->tv_sec || a->tv_usec;
92}
93
94int
Denys Vlasenko12014262011-05-30 14:00:14 +020095tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096{
97 if (a->tv_sec < b->tv_sec
98 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
99 return -1;
100 if (a->tv_sec > b->tv_sec
101 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
102 return 1;
103 return 0;
104}
105
106double
Denys Vlasenko12014262011-05-30 14:00:14 +0200107tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 return tv->tv_sec + tv->tv_usec/1000000.0;
110}
111
112void
Denys Vlasenko12014262011-05-30 14:00:14 +0200113tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114{
115 tv->tv_sec = a->tv_sec + b->tv_sec;
116 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000117 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 tv->tv_sec++;
119 tv->tv_usec -= 1000000;
120 }
121}
122
123void
Denys Vlasenko12014262011-05-30 14:00:14 +0200124tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125{
126 tv->tv_sec = a->tv_sec - b->tv_sec;
127 tv->tv_usec = a->tv_usec - b->tv_usec;
128 if (((long) tv->tv_usec) < 0) {
129 tv->tv_sec--;
130 tv->tv_usec += 1000000;
131 }
132}
133
134void
Denys Vlasenko12014262011-05-30 14:00:14 +0200135tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136{
137 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
138 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
139 tv->tv_usec %= 1000000;
140}
141
142void
Denys Vlasenko12014262011-05-30 14:00:14 +0200143tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144{
145 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000146 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147 tv->tv_usec %= 1000000;
148}
149
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000150const char *
151xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152{
153 for (; xlat->str != NULL; xlat++)
154 if (xlat->val == val)
155 return xlat->str;
156 return NULL;
157}
158
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200159#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200160char *
161stpcpy(char *dst, const char *src)
162{
163 while ((*dst = *src++) != '\0')
164 dst++;
165 return dst;
166}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200167#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200168
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169/*
Roland McGratheb9e2e82009-06-02 16:49:22 -0700170 * Generic ptrace wrapper which tracks ESRCH errors
171 * by setting tcp->ptrace_errno to ESRCH.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000172 *
173 * We assume that ESRCH indicates likely process death (SIGKILL?),
174 * modulo bugs where process somehow ended up not stopped.
175 * Unfortunately kernel uses ESRCH for that case too. Oh well.
Roland McGratheb9e2e82009-06-02 16:49:22 -0700176 *
177 * Currently used by upeek() only.
178 * TODO: use this in all other ptrace() calls while decoding.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000179 */
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000180long
Roland McGratheb9e2e82009-06-02 16:49:22 -0700181do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000182{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000183 long l;
184
185 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400186 l = ptrace(request, tcp->pid, addr, (long) data);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700187 /* Non-ESRCH errors might be our invalid reg/mem accesses,
188 * we do not record them. */
189 if (errno == ESRCH)
190 tcp->ptrace_errno = ESRCH;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000191 return l;
192}
193
194/*
195 * Used when we want to unblock stopped traced process.
196 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
197 * Returns 0 on success or if error was ESRCH
198 * (presumably process was killed while we talk to it).
199 * Otherwise prints error message and returns -1.
200 */
201int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700202ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000203{
204 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700205 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000206
207 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400208 ptrace(op, tcp->pid, (void *) 1, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000209 err = errno;
210 if (!err || err == ESRCH)
211 return 0;
212
213 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700214 msg = "SYSCALL";
215 if (op == PTRACE_CONT)
216 msg = "CONT";
217 if (op == PTRACE_DETACH)
218 msg = "DETACH";
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100219#ifdef PTRACE_LISTEN
220 if (op == PTRACE_LISTEN)
221 msg = "LISTEN";
222#endif
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200223 perror_msg("ptrace(PTRACE_%s,1,%d)", msg, sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000224 return -1;
225}
226
227/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228 * Print entry in struct xlat table, if there.
229 */
230void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000231printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000233 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234
235 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200236 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 else
238 tprintf("%#x /* %s */", val, dflt);
239}
240
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100241#if HAVE_LONG_LONG
242/*
243 * Print 64bit argument at position llarg and return the index of the next
244 * argument.
245 */
246int
247printllval(struct tcb *tcp, const char *format, int llarg)
248{
Denys Vlasenko84703742012-02-25 02:38:52 +0100249# if defined X86_64 || defined POWERPC64
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100250 if (current_personality == 0) {
251 tprintf(format, tcp->u_arg[llarg]);
252 llarg++;
253 } else {
Andreas Schwabd69fa492010-07-12 21:39:57 +0200254# ifdef POWERPC64
255 /* Align 64bit argument to 64bit boundary. */
Denys Vlasenko4b08df42011-08-19 15:58:24 +0200256 llarg = (llarg + 1) & 0x1e;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200257# endif
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100258 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
259 llarg += 2;
260 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200261# elif defined IA64 || defined ALPHA
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100262 tprintf(format, tcp->u_arg[llarg]);
263 llarg++;
264# elif defined LINUX_MIPSN32
265 tprintf(format, tcp->ext_arg[llarg]);
266 llarg++;
267# else
268 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
269 llarg += 2;
270# endif
271 return llarg;
272}
273#endif
274
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000275/*
276 * Interpret `xlat' as an array of flags
277 * print the entries whose bits are on in `flags'
278 * return # of flags printed.
279 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200280void
Denys Vlasenko12014262011-05-30 14:00:14 +0200281addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200283 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284 if (xlat->val && (flags & xlat->val) == xlat->val) {
285 tprintf("|%s", xlat->str);
286 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287 }
288 }
289 if (flags) {
290 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000292}
293
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000294/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200295 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000296 * Print to static string the entries whose bits are on in `flags'
297 * Return static string.
298 */
299const char *
300sprintflags(const char *prefix, const struct xlat *xlat, int flags)
301{
302 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200303 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000304 int found = 0;
305
Denys Vlasenko52845572011-08-31 12:07:38 +0200306 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000307
308 for (; xlat->str; xlat++) {
309 if ((flags & xlat->val) == xlat->val) {
310 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200311 *outptr++ = '|';
312 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000313 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100314 flags &= ~xlat->val;
315 if (!flags)
316 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000317 }
318 }
319 if (flags) {
320 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200321 *outptr++ = '|';
322 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000323 }
324
325 return outstr;
326}
327
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000329printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000330{
331 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000332 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333
334 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200335 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336 return 1;
337 }
338
339 sep = "";
340 for (n = 0; xlat->str; xlat++) {
341 if (xlat->val && (flags & xlat->val) == xlat->val) {
342 tprintf("%s%s", sep, xlat->str);
343 flags &= ~xlat->val;
344 sep = "|";
345 n++;
346 }
347 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000348
349 if (n) {
350 if (flags) {
351 tprintf("%s%#x", sep, flags);
352 n++;
353 }
354 } else {
355 if (flags) {
356 tprintf("%#x", flags);
357 if (dflt)
358 tprintf(" /* %s */", dflt);
359 } else {
360 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200361 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000362 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000363 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000364
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000365 return n;
366}
367
368void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000369printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370{
Roland McGratheb285352003-01-14 09:59:00 +0000371 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372
373 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200374 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375 return;
376 }
377 if (umove(tcp, addr, &num) < 0) {
378 tprintf("%#lx", addr);
379 return;
380 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200381 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200383 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384}
385
Roland McGrath6bc12202003-11-13 22:32:27 +0000386void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000387printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000388{
389 int num;
390
391 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200392 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000393 return;
394 }
395 if (umove(tcp, addr, &num) < 0) {
396 tprintf("%#lx", addr);
397 return;
398 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200399 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000400 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200401 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000402}
403
404void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300405printfd(struct tcb *tcp, int fd)
406{
Grant Edwards8a082772011-04-07 20:25:40 +0000407 const char *p;
408
409 if (show_fd_path && (p = getfdpath(tcp, fd)))
410 tprintf("%d<%s>", fd, p);
411 else
412 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300413}
414
415void
Denys Vlasenko12014262011-05-30 14:00:14 +0200416printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000417{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200418 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000419}
420
Dmitry V. Levina501f142008-11-10 23:19:13 +0000421/*
422 * Quote string `instr' of length `size'
423 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
424 * If `len' < 0, treat `instr' as a NUL-terminated string
425 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100426 *
427 * Returns 0 if len < 0 and NUL was seen, 1 otherwise.
428 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000429 */
Roland McGrath6d970322007-11-01 23:53:59 +0000430static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000431string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000432{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000433 const unsigned char *ustr = (const unsigned char *) instr;
434 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200435 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200437 eol = 0x100; /* this can never match a char */
438 if (len < 0) {
439 size--;
440 eol = '\0';
441 }
442
443 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000444 if (xflag > 1)
445 usehex = 1;
446 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000447 /* Check for presence of symbol which require
448 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000449 for (i = 0; i < size; ++i) {
450 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000451 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200452 if (c == eol)
453 break;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000454 if (!isprint(c) && !isspace(c)) {
455 usehex = 1;
456 break;
457 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000458 }
459 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000460
461 *s++ = '\"';
462
463 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000464 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000465 for (i = 0; i < size; ++i) {
466 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000467 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200468 if (c == eol)
469 goto asciz_ended;
470 *s++ = '\\';
471 *s++ = 'x';
472 *s++ = "0123456789abcdef"[c >> 4];
473 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000474 }
475 } else {
476 for (i = 0; i < size; ++i) {
477 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000478 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200479 if (c == eol)
480 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000481 switch (c) {
482 case '\"': case '\\':
483 *s++ = '\\';
484 *s++ = c;
485 break;
486 case '\f':
487 *s++ = '\\';
488 *s++ = 'f';
489 break;
490 case '\n':
491 *s++ = '\\';
492 *s++ = 'n';
493 break;
494 case '\r':
495 *s++ = '\\';
496 *s++ = 'r';
497 break;
498 case '\t':
499 *s++ = '\\';
500 *s++ = 't';
501 break;
502 case '\v':
503 *s++ = '\\';
504 *s++ = 'v';
505 break;
506 default:
507 if (isprint(c))
508 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200509 else {
510 /* Print \octal */
511 *s++ = '\\';
512 if (i + 1 < size
513 && ustr[i + 1] >= '0'
514 && ustr[i + 1] <= '9'
515 ) {
516 /* Print \ooo */
517 *s++ = '0' + (c >> 6);
518 *s++ = '0' + ((c >> 3) & 0x7);
519 } else {
520 /* Print \[[o]o]o */
521 if ((c >> 3) != 0) {
522 if ((c >> 6) != 0)
523 *s++ = '0' + (c >> 6);
524 *s++ = '0' + ((c >> 3) & 0x7);
525 }
526 }
527 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528 }
529 break;
530 }
531 }
532 }
533
534 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000535 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000536
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200537 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
538 if (len < 0 && ustr[i] == '\0') {
539 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
540 * but next char is NUL.
541 */
542 return 0;
543 }
544
545 return 1;
546
547 asciz_ended:
548 *s++ = '\"';
549 *s = '\0';
550 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
551 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552}
553
Dmitry V. Levina501f142008-11-10 23:19:13 +0000554/*
555 * Print path string specified by address `addr' and length `n'.
556 * If path length exceeds `n', append `...' to the output.
557 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000559printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100561 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100562 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100563
Dmitry V. Levina501f142008-11-10 23:19:13 +0000564 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200565 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000566 return;
567 }
568
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100569 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000570 if (n > sizeof path - 1)
571 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000572
573 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100574 nul_seen = umovestr(tcp, addr, n + 1, path);
575 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000576 tprintf("%#lx", addr);
577 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100578 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000579
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100580 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100581 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100582 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100583 string_quote(path, outstr, -1, n);
584 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100585 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100586 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000587 }
588}
589
590void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000591printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100593 /* Size must correspond to char path[] size in printpathn */
594 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000595}
596
Dmitry V. Levina501f142008-11-10 23:19:13 +0000597/*
598 * Print string specified by address `addr' and length `len'.
599 * If `len' < 0, treat the string as a NUL-terminated string.
600 * If string length exceeds `max_strlen', append `...' to the output.
601 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000602void
603printstr(struct tcb *tcp, long addr, int len)
604{
605 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000607 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100608 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000609
610 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200611 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612 return;
613 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000614 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200615 if (!str) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000616 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200617 if (!str)
618 die_out_of_memory();
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100619 outstr = malloc(4 * max_strlen + /*for quotes and NUL:*/ 3);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200620 if (!outstr)
621 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000622 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000623
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000625 /*
626 * Treat as a NUL-terminated string: fetch one byte more
627 * because string_quote() quotes one byte less.
628 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000629 size = max_strlen + 1;
630 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 tprintf("%#lx", addr);
632 return;
633 }
634 }
635 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000636 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000637 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000638 tprintf("%#lx", addr);
639 return;
640 }
641 }
642
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100643 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
644 * or we were requested to print more than -s NUM chars)...
645 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100646 ellipsis = (string_quote(str, outstr, len, size) &&
647 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000648
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100649 tprints(outstr);
650 if (ellipsis)
651 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652}
653
John Hughes1d08dcf2001-07-10 13:48:44 +0000654#if HAVE_SYS_UIO_H
655void
Denys Vlasenko12014262011-05-30 14:00:14 +0200656dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000657{
Denys Vlasenko84703742012-02-25 02:38:52 +0100658#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000659 union {
660 struct { u_int32_t base; u_int32_t len; } *iov32;
661 struct { u_int64_t base; u_int64_t len; } *iov64;
662 } iovu;
663#define iov iovu.iov64
664#define sizeof_iov \
665 (personality_wordsize[current_personality] == 4 \
666 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
667#define iov_iov_base(i) \
668 (personality_wordsize[current_personality] == 4 \
669 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
670#define iov_iov_len(i) \
671 (personality_wordsize[current_personality] == 4 \
672 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
673#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000674 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000675#define sizeof_iov sizeof(*iov)
676#define iov_iov_base(i) iov[i].iov_base
677#define iov_iov_len(i) iov[i].iov_len
678#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000679 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200680 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000681
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200682 size = sizeof_iov * len;
683 /* Assuming no sane program has millions of iovs */
684 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000685 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200686 fprintf(stderr, "Out of memory\n");
687 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000688 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000689 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000690 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000691 /* include the buffer number to make it easy to
692 * match up the trace with the source */
693 tprintf(" * %lu bytes in buffer %d\n",
694 (unsigned long)iov_iov_len(i), i);
695 dumpstr(tcp, (long) iov_iov_base(i),
696 iov_iov_len(i));
697 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000698 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200699 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000700#undef sizeof_iov
701#undef iov_iov_base
702#undef iov_iov_len
703#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000704}
705#endif
706
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000707void
Denys Vlasenko12014262011-05-30 14:00:14 +0200708dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709{
710 static int strsize = -1;
711 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 char *s;
713 int i, j;
714
715 if (strsize < len) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200716 free(str);
717 str = malloc(len);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200718 if (!str) {
719 strsize = -1;
720 fprintf(stderr, "Out of memory\n");
721 return;
722 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 strsize = len;
724 }
725
726 if (umoven(tcp, addr, len, (char *) str) < 0)
727 return;
728
729 for (i = 0; i < len; i += 16) {
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200730 char outstr[80];
731
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732 s = outstr;
733 sprintf(s, " | %05x ", i);
734 s += 9;
735 for (j = 0; j < 16; j++) {
736 if (j == 8)
737 *s++ = ' ';
738 if (i + j < len) {
739 sprintf(s, " %02x", str[i + j]);
740 s += 3;
741 }
742 else {
743 *s++ = ' '; *s++ = ' '; *s++ = ' ';
744 }
745 }
746 *s++ = ' '; *s++ = ' ';
747 for (j = 0; j < 16; j++) {
748 if (j == 8)
749 *s++ = ' ';
750 if (i + j < len) {
751 if (isprint(str[i + j]))
752 *s++ = str[i + j];
753 else
754 *s++ = '.';
755 }
756 else
757 *s++ = ' ';
758 }
759 tprintf("%s |\n", outstr);
760 }
761}
762
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100763
Mike Frysinger612659e2012-02-14 14:38:28 +0100764#ifdef HAVE_PROCESS_VM_READV
765/* C library supports this, but the kernel might not. */
766static bool process_vm_readv_not_supported = 0;
767#else
768
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100769/* Need to do this since process_vm_readv() is not yet available in libc.
770 * When libc is be updated, only "static bool process_vm_readv_not_supported"
771 * line should remain.
772 */
773#if !defined(__NR_process_vm_readv)
774# if defined(I386)
775# define __NR_process_vm_readv 347
776# elif defined(X86_64)
777# define __NR_process_vm_readv 310
778# elif defined(POWERPC)
779# define __NR_process_vm_readv 351
780# endif
781#endif
782
783#if defined(__NR_process_vm_readv)
784static bool process_vm_readv_not_supported = 0;
785static ssize_t process_vm_readv(pid_t pid,
786 const struct iovec *lvec,
787 unsigned long liovcnt,
788 const struct iovec *rvec,
789 unsigned long riovcnt,
790 unsigned long flags)
791{
792 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
793}
794#else
795static bool process_vm_readv_not_supported = 1;
796# define process_vm_readv(...) (errno = ENOSYS, -1)
797#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100798
799#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100800
801
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802#define PAGMASK (~(PAGSIZ - 1))
803/*
804 * move `len' bytes of data from process `pid'
805 * at address `addr' to our space at `laddr'
806 */
807int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000808umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000809{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700810 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 int n, m;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100812 int started;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 union {
814 long val;
815 char x[sizeof(long)];
816 } u;
817
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100818#if SUPPORTED_PERSONALITIES > 1
819 if (personality_wordsize[current_personality] < sizeof(addr))
820 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
821#endif
822
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100823 if (!process_vm_readv_not_supported) {
824 struct iovec local[1], remote[1];
825 int r;
826
827 local[0].iov_base = laddr;
828 remote[0].iov_base = (void*)addr;
829 local[0].iov_len = remote[0].iov_len = len;
830 r = process_vm_readv(pid,
831 local, 1,
832 remote, 1,
833 /*flags:*/ 0
834 );
835 if (r < 0) {
836 if (errno == ENOSYS)
837 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100838 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
839 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100840 perror("process_vm_readv");
841 goto vm_readv_didnt_work;
842 }
843 return r;
844 }
845 vm_readv_didnt_work:
846
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100847 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000848 if (addr & (sizeof(long) - 1)) {
849 /* addr not a multiple of sizeof(long) */
850 n = addr - (addr & -sizeof(long)); /* residue */
851 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700852 errno = 0;
853 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
854 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700855 /* But if not started, we had a bogus address. */
856 if (addr != 0 && errno != EIO && errno != ESRCH)
857 perror("ptrace: umoven");
858 return -1;
859 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000860 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100861 m = MIN(sizeof(long) - n, len);
862 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 addr += sizeof(long), laddr += m, len -= m;
864 }
865 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700866 errno = 0;
867 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
868 if (errno) {
869 if (started && (errno==EPERM || errno==EIO)) {
870 /* Ran into 'end of memory' - stupid "printpath" */
871 return 0;
872 }
873 if (addr != 0 && errno != EIO && errno != ESRCH)
874 perror("ptrace: umoven");
875 return -1;
876 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000877 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100878 m = MIN(sizeof(long), len);
879 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880 addr += sizeof(long), laddr += m, len -= m;
881 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884
885 return 0;
886}
887
888/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100889 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100891 *
892 * Returns < 0 on error, > 0 if NUL was seen,
893 * (TODO if useful: return count of bytes including NUL),
894 * else 0 if len bytes were read but no NUL byte seen.
895 *
896 * Note: there is no guarantee we won't overwrite some bytes
897 * in laddr[] _after_ terminating NUL (but, of course,
898 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000899 */
900int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000901umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902{
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100903 int started;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700904 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 int i, n, m;
906 union {
907 long val;
908 char x[sizeof(long)];
909 } u;
910
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000911#if SUPPORTED_PERSONALITIES > 1
912 if (personality_wordsize[current_personality] < sizeof(addr))
913 addr &= (1ul << 8 * personality_wordsize[current_personality]) - 1;
914#endif
915
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100916 if (!process_vm_readv_not_supported) {
917 struct iovec local[1], remote[1];
918
919 local[0].iov_base = laddr;
920 remote[0].iov_base = (void*)addr;
921
922 while (len > 0) {
923 int end_in_page;
924 int r;
925 int chunk_len;
926
927 /* Don't read kilobytes: most strings are short */
928 chunk_len = len;
929 if (chunk_len > 256)
930 chunk_len = 256;
931 /* Don't cross pages. I guess otherwise we can get EFAULT
932 * and fail to notice that terminating NUL lies
933 * in the existing (first) page.
934 * (I hope there aren't arches with pages < 4K)
935 */
936 end_in_page = ((addr + chunk_len) & 4095);
937 r = chunk_len - end_in_page;
938 if (r > 0) /* if chunk_len > end_in_page */
939 chunk_len = r; /* chunk_len -= end_in_page */
940
941 local[0].iov_len = remote[0].iov_len = chunk_len;
942 r = process_vm_readv(pid,
943 local, 1,
944 remote, 1,
945 /*flags:*/ 0
946 );
947 if (r < 0) {
948 if (errno == ENOSYS)
949 process_vm_readv_not_supported = 1;
Denys Vlasenko29456392012-01-28 02:49:48 +0100950 else if (errno != EINVAL) /* EINVAL is seen if process is gone */
951 /* strange... */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100952 perror("process_vm_readv");
953 goto vm_readv_didnt_work;
954 }
955 if (memchr(local[0].iov_base, '\0', r))
956 return 1;
957 local[0].iov_base += r;
958 remote[0].iov_base += r;
959 len -= r;
960 }
961 return 0;
962 }
963 vm_readv_didnt_work:
964
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100965 started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 if (addr & (sizeof(long) - 1)) {
967 /* addr not a multiple of sizeof(long) */
968 n = addr - (addr & -sizeof(long)); /* residue */
969 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700970 errno = 0;
971 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
972 if (errno) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700973 if (addr != 0 && errno != EIO && errno != ESRCH)
974 perror("umovestr");
975 return -1;
976 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000977 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100978 m = MIN(sizeof(long) - n, len);
979 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980 while (n & (sizeof(long) - 1))
981 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100982 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 addr += sizeof(long), laddr += m, len -= m;
984 }
985 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700986 errno = 0;
987 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
988 if (errno) {
989 if (started && (errno==EPERM || errno==EIO)) {
990 /* Ran into 'end of memory' - stupid "printpath" */
991 return 0;
992 }
993 if (addr != 0 && errno != EIO && errno != ESRCH)
994 perror("umovestr");
995 return -1;
996 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000997 started = 1;
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100998 m = MIN(sizeof(long), len);
999 memcpy(laddr, u.x, m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 for (i = 0; i < sizeof(long); i++)
1001 if (u.x[i] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001002 return 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 addr += sizeof(long), laddr += m, len -= m;
1004 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001005 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006}
1007
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001008# if !defined (SPARC) && !defined(SPARC64)
1009# define PTRACE_WRITETEXT 101
1010# define PTRACE_WRITEDATA 102
1011# endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014
1015int
Denys Vlasenko12014262011-05-30 14:00:14 +02001016upeek(struct tcb *tcp, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017{
1018 long val;
1019
Roland McGratheb9e2e82009-06-02 16:49:22 -07001020 errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001021 val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001022 if (val == -1 && errno) {
1023 if (errno != ESRCH) {
1024 char buf[60];
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001025 sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001026 perror(buf);
1027 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001029 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030 *res = val;
1031 return 0;
1032}
1033
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001036printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037{
Roland McGrath7a918832005-02-02 20:55:23 +00001038#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1039 sizeof(long) == 8 ? "[????????????????] " : \
1040 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001042# ifdef I386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 long eip;
1044
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001045 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001046 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 return;
1048 }
1049 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001050
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001051# elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001052 long psw;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001053 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001054 PRINTBADPC;
1055 return;
1056 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001057# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001058 tprintf("[%08lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001059# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001060 tprintf("[%16lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001061# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001062
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001063# elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001064 long rip;
1065
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001066 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001067 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001068 return;
1069 }
1070 tprintf("[%16lx] ", rip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001071# elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001072 long ip;
1073
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001074 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001075 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001076 return;
1077 }
1078 tprintf("[%08lx] ", ip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001079# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080 long pc;
1081
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001082 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Andreas Schwabd69fa492010-07-12 21:39:57 +02001083 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 return;
1085 }
Andreas Schwabd69fa492010-07-12 21:39:57 +02001086# ifdef POWERPC64
1087 tprintf("[%016lx] ", pc);
1088# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089 tprintf("[%08lx] ", pc);
Andreas Schwabd69fa492010-07-12 21:39:57 +02001090# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001091# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 long pc;
1093
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001095 tprints("[????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 return;
1097 }
1098 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001099# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 long pc;
1101
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001102 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001103 tprints("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 return;
1105 }
1106 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001107# elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001108 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001109 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001110 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111 return;
1112 }
Mike Frysinger8566c502009-10-12 11:05:14 -04001113# if defined(SPARC64)
1114 tprintf("[%08lx] ", regs.tpc);
1115# else
1116 tprintf("[%08lx] ", regs.pc);
1117# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001118# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001119 long pc;
1120
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001121 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001122 tprints("[????????] ");
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001123 return;
1124 }
1125 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001126# elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001127 long pc;
1128
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001129 if (upeek(tcp, REG_EPC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001130 tprints("[????????] ");
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001131 return;
1132 }
1133 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001134# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001135 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001136
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001137 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001138 tprints("[????????] ");
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001139 return;
1140 }
1141 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001142# elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001143 long pc;
1144
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001145 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001146 tprints("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001147 return;
1148 }
1149 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001150# elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001151 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001152
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001153 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001154 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001155 return;
1156 }
1157 tprintf("[%08lx] ", pc);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001158# elif defined(AVR32)
1159 long pc;
1160
1161 if (upeek(tcp, REG_PC, &pc) < 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001162 tprints("[????????] ");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001163 return;
1164 }
1165 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001166# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001167 long pc;
1168
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001169 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001170 PRINTBADPC;
1171 return;
1172 }
1173 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001174#elif defined(CRISV10)
1175 long pc;
1176
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001177 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001178 PRINTBADPC;
1179 return;
1180 }
1181 tprintf("[%08lx] ", pc);
1182#elif defined(CRISV32)
1183 long pc;
1184
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001185 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001186 PRINTBADPC;
1187 return;
1188 }
1189 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001190# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194}
1195
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001196
1197/*
1198 * These #if's are huge, please indent them correctly.
1199 * It's easy to get confused otherwise.
1200 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001203# include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001204
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001205# include <sys/syscall.h>
1206# ifndef CLONE_PTRACE
1207# define CLONE_PTRACE 0x00002000
1208# endif
1209# ifndef CLONE_VFORK
1210# define CLONE_VFORK 0x00004000
1211# endif
1212# ifndef CLONE_VM
1213# define CLONE_VM 0x00000100
1214# endif
1215# ifndef CLONE_STOPPED
1216# define CLONE_STOPPED 0x02000000
1217# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001218
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001219# ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220
1221typedef unsigned long *arg_setup_state;
1222
1223static int
1224arg_setup(struct tcb *tcp, arg_setup_state *state)
1225{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001226 unsigned long cfm, sof, sol;
1227 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001228
Jan Kratochvil1f942712008-08-06 21:38:52 +00001229 if (ia32) {
1230 /* Satisfy a false GCC warning. */
1231 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001232 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001233 }
Roland McGrath08267b82004-02-20 22:56:43 +00001234
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001235 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001236 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001237 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001238 return -1;
1239
1240 sof = (cfm >> 0) & 0x7f;
1241 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001242 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001243
Jan Kratochvil1f942712008-08-06 21:38:52 +00001244 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001245 return 0;
1246}
1247
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001248# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001249
Roland McGrathd81f1d92003-01-09 06:53:34 +00001250static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001251get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252{
Roland McGrath08267b82004-02-20 22:56:43 +00001253 int ret;
1254
1255 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001256 ret = upeek(tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001257 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001258 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001259 (unsigned long) ia64_rse_skip_regs(*state, 0),
1260 sizeof(long), (void *) valp);
1261 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262}
1263
1264static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001265get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001266{
Roland McGrath08267b82004-02-20 22:56:43 +00001267 int ret;
1268
1269 if (ia32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001270 ret = upeek(tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001271 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001272 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001273 (unsigned long) ia64_rse_skip_regs(*state, 1),
1274 sizeof(long), (void *) valp);
1275 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001276}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277
1278static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001279set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001280{
Roland McGrath08267b82004-02-20 22:56:43 +00001281 int req = PTRACE_POKEDATA;
1282 void *ap;
1283
1284 if (ia32) {
1285 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1286 req = PTRACE_POKEUSER;
1287 } else
1288 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001289 errno = 0;
1290 ptrace(req, tcp->pid, ap, val);
1291 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292}
1293
1294static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001295set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296{
Roland McGrath08267b82004-02-20 22:56:43 +00001297 int req = PTRACE_POKEDATA;
1298 void *ap;
1299
1300 if (ia32) {
1301 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1302 req = PTRACE_POKEUSER;
1303 } else
1304 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001305 errno = 0;
1306 ptrace(req, tcp->pid, ap, val);
1307 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001308}
1309
Roland McGrathb659f872008-07-18 01:19:36 +00001310/* ia64 does not return the input arguments from functions (and syscalls)
1311 according to ia64 RSE (Register Stack Engine) behavior. */
1312
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001313# define restore_arg0(tcp, state, val) ((void) (state), 0)
1314# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001315
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001316# elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317
Mike Frysinger8566c502009-10-12 11:05:14 -04001318typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001319
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001320# define arg_setup(tcp, state) \
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001321 (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001322# define arg_finish_change(tcp, state) \
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001323 (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324
Mike Frysinger8566c502009-10-12 11:05:14 -04001325# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1326# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1327# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1328# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001329# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001330
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001331# else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001333# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001334/* Note: this is only true for the `clone' system call, which handles
1335 arguments specially. We could as well say that its first two arguments
1336 are swapped relative to other architectures, but that would just be
1337 another #ifdef in the calls. */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001338# define arg0_offset PT_GPR3
1339# define arg1_offset PT_ORIGGPR2
1340# define restore_arg0(tcp, state, val) ((void) (state), 0)
1341# define restore_arg1(tcp, state, val) ((void) (state), 0)
1342# define arg0_index 1
1343# define arg1_index 0
1344# elif defined (ALPHA) || defined (MIPS)
1345# define arg0_offset REG_A0
1346# define arg1_offset (REG_A0+1)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001347# elif defined (AVR32)
1348# define arg0_offset (REG_R12)
1349# define arg1_offset (REG_R11)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001350# elif defined (POWERPC)
1351# define arg0_offset (sizeof(unsigned long)*PT_R3)
1352# define arg1_offset (sizeof(unsigned long)*PT_R4)
1353# define restore_arg0(tcp, state, val) ((void) (state), 0)
1354# elif defined (HPPA)
1355# define arg0_offset PT_GR26
1356# define arg1_offset (PT_GR26-4)
1357# elif defined (X86_64)
1358# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1359# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1360# elif defined (SH)
1361# define arg0_offset (4*(REG_REG0+4))
1362# define arg1_offset (4*(REG_REG0+5))
1363# elif defined (SH64)
1364 /* ABI defines arg0 & 1 in r2 & r3 */
1365# define arg0_offset (REG_OFFSET+16)
1366# define arg1_offset (REG_OFFSET+24)
1367# define restore_arg0(tcp, state, val) 0
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001368# elif defined CRISV10 || defined CRISV32
1369# define arg0_offset (4*PT_R11)
1370# define arg1_offset (4*PT_ORIG_R10)
1371# define restore_arg0(tcp, state, val) 0
1372# define restore_arg1(tcp, state, val) 0
1373# define arg0_index 1
1374# define arg1_index 0
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001375# else
1376# define arg0_offset 0
1377# define arg1_offset 4
1378# if defined ARM
1379# define restore_arg0(tcp, state, val) 0
1380# endif
1381# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001382
1383typedef int arg_setup_state;
1384
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001385# define arg_setup(tcp, state) (0)
1386# define arg_finish_change(tcp, state) 0
1387# define get_arg0(tcp, cookie, valp) \
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001388 (upeek((tcp), arg0_offset, (valp)))
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001389# define get_arg1(tcp, cookie, valp) \
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001390 (upeek((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001391
1392static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001393set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001394{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001395 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001396}
1397
1398static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001399set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001400{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001401 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001402}
1403
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001404# endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001405
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001406# ifndef restore_arg0
1407# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1408# endif
1409# ifndef restore_arg1
1410# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1411# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001413# ifndef arg0_index
1414# define arg0_index 0
1415# define arg1_index 1
1416# endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001417
Roland McGrathd81f1d92003-01-09 06:53:34 +00001418int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001419setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420{
Roland McGrath3291ef22008-05-20 00:34:34 +00001421 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422 arg_setup_state state;
1423
1424 if (tcp->flags & TCB_BPTSET) {
1425 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1426 return -1;
1427 }
1428
Roland McGrath3291ef22008-05-20 00:34:34 +00001429 /*
1430 * It's a silly kludge to initialize this with a search at runtime.
1431 * But it's better than maintaining another magic thing in the
1432 * godforsaken tables.
1433 */
1434 if (clone_scno[current_personality] == 0) {
1435 int i;
1436 for (i = 0; i < nsyscalls; ++i)
1437 if (sysent[i].sys_func == sys_clone) {
1438 clone_scno[current_personality] = i;
1439 break;
1440 }
1441 }
1442
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001443 if (sysent[tcp->scno].sys_func == sys_fork ||
1444 sysent[tcp->scno].sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 if (arg_setup(tcp, &state) < 0
1446 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1447 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001448 || change_syscall(tcp, clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001449 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1450 || set_arg1(tcp, &state, 0) < 0
1451 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001452 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001453 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1454 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455 tcp->flags |= TCB_BPTSET;
1456 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001457 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001458
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001459 if (sysent[tcp->scno].sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001460 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001461 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001462 vfork semantics into plain fork - each application must not
1463 depend on the vfork specifics according to POSIX. We would
1464 hang waiting for the parent resume otherwise. We need to
1465 clear also CLONE_VM but only in the CLONE_VFORK case as
1466 otherwise we would break pthread_create. */
1467
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001468 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1469 if (new_arg0 & CLONE_VFORK)
1470 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1471 if (arg_setup(tcp, &state) < 0
1472 || set_arg0(tcp, &state, new_arg0) < 0
1473 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001474 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001475 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001476 tcp->inst[0] = tcp->u_arg[arg0_index];
1477 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001478 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479 }
1480
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001481 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1482 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483 return -1;
1484}
1485
1486int
Denys Vlasenko12014262011-05-30 14:00:14 +02001487clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001488{
1489 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001490 if (arg_setup(tcp, &state) < 0
1491 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1492 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1493 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001494 if (errno != ESRCH)
1495 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001496 tcp->flags &= ~TCB_BPTSET;
1497 return 0;
1498}
1499
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001501
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502